<?php
/**
* Web Application Component Toolkit
*
* @link http://www.phpwact.org/
*
* @author Wact Development Team
* @link http://www.phpwact.org/team
*
* @copyright Copyright 2006, Jeff Moore
* @license http://opensource.org/licenses/mit-license.php MIT
*/

/*
* This parameter type represents a value derived from another parameter by
* dividing that base parameter up into segments.
* Segmented parameters are related by their baseName's and they write (collect) values
* to the CHANNEL_DERIVED channel until the top-level segmented parameter is reached.
* The top-level segmented parameter writes the joined segments
* through its base parameter (e.g. a pathinfo parameter) to the transition.
*/
class Wact_Request_Segmented extends Wact_Request_Parameter {

    /**
    * The basis for our segmentation
    * @var Wact_Request_Parameter 
    */
    protected $baseName;
    
    /**
    * The controller that this parameter is associated with
    * @var Wact_Controller_Base
    */
    protected $definingController;    
    
    private $segmentationPattern = '/^\/(.*)(\/.*){0,1}$/U';
    
    /**
    * Construct this parameter
    */
    function __construct($name, $baseName = NULL) {
        $this->baseName = $baseName;
        parent::__construct($name);
    }

    /**
    */
    function getBaseName() {
        return $this->baseName;
    }

    /**
    */
    function bindToController($definingController) {
        $this->definingController = $definingController;
    }

    /**
    */
    function getBaseParameter() {
        $focus = $this->definingController;
        while ($focus) {
            $parameters = $focus->getParameters();

            // look for a related segmented parameter
            foreach(array_reverse(array_keys($parameters)) as $key) {
                $parameter = $parameters[$key];
                if ($parameter === $this) {
                    continue;
                }
                if ($parameter instanceof Wact_Request_Segmented) {
                    if ($parameter->getBaseName() == $this->baseName) {
                        return $parameter;
                    }
                }
            }
            
            // no related segmented parameters found
            // let's see if the top-level base parameter is here
            foreach(array_reverse(array_keys($parameters)) as $key) {
                $parameter = $parameters[$key];
                if ($parameter === $this) {
                    continue;
                }
                if (!$parameter instanceof Wact_Request_Segmented) {
                    if ($parameter->getName() == $this->baseName) {
                        return $parameter;
                    }
                }
            }
          
            $focus = $focus->parent;
        }
        throw new Wact_Request_Exception('Segment base not found');
    }

    /**
    */
    function getRestOfSegment() {
        $base = $this->getBaseParameter();
        
        if (method_exists($base, 'getRestOfSegment')) {
            $value = $base->getRestOfSegment();
        } else {
            $value = $base->getRawValue();
        }

        // take /foo/bar and return /bar        

        if (preg_match($this->segmentationPattern, $value, $matches)) {
            return $matches[2];
        } else {
            die("what happens now?");
        }

    }

    /**
    */
    function getRawValue() {
        $base = $this->getBaseParameter();
        
        if (method_exists($base, 'getRestOfSegment')) {
            $baseValue = $base->getRestOfSegment();
        } else {
            $baseValue = $base->getRawValue();
        }

        //take /foo/bar and return foo
        if (preg_match($this->segmentationPattern, $baseValue, $matches)) {
            return $matches[1];
        } else {
            die("What happens now?");
        }
    }
    
    /**
    * 
    */
    function hasValue() {
        $base = $this->getBaseParameter();

        if ($base->hasValue()) {
            if (method_exists($base, 'getRestOfSegment')) {
                $value = $base->getRestOfSegment();
            } else {
                $value = $base->getRawValue();
            }
            
            return (boolean) preg_match($this->segmentationPattern, $value);
        } else {
            return FALSE;
        }

    }

    protected function joinSegment($value, $segment) {
        if (empty($value) && empty($segment)) {
            return '';
        } else {
            if (empty($segment)) {
                return $value;
            } else {
                return $value . '/' . $segment;
            }
        }
    }

    /**
    */
    function WriteValueToTransition($transition, $value) {
        
        $segment = $transition->readValueFromChannel(
            Wact_Controller_Transition_Link::CHANNEL_DERIVED, 
            $this->baseName);
            
        $value = $this->joinSegment($value, $segment);

        if (!empty($segment) || $this->getDefault() !== $value) {
            $base = $this->getBaseParameter();
            if ($base instanceof Wact_Request_Segmented) {
                $transition->writeValueToChannel(Wact_Controller_Transition_Link::CHANNEL_DERIVED, 
                    $this->baseName,
                    $value);
            } else {
                $base->writeValueToTransition($transition, $value);
            }
        }
    }

}

?>