<?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
*/

/**
* A Template node which has a corresponding Partial view object.
*/
class Wact_Template_Compiler_Node_View extends Wact_Template_Compiler_Node {

    /**
    * @var string
    */
    public $parentViewClass = 'Wact_View_Partial';

    /**
    */
    protected $viewClass;
    
    /**
    */
    private static $classIdCounter = 1;

    /**
    * Returns the view class name associated with this node
    * @return string
    */
    function getViewClass() {
        if (empty($this->viewClass)) {
            $this->viewClass = $this->root->getViewClass() . 
                '_' . self::$classIdCounter++ . '_' . 
                $this->getViewId();
        }
        return $this->viewClass;
    }

    /**
    * Generate the code to instantiate this class
    * @param Wact_Php_Writer $code
    */
    function generateInstantiation($code) {
        $code->writePHP('new ' . $this->getViewClass() . '()');
    }

    /**
    * Generate the code to add the node to the parent class
    * @param Wact_Php_Writer $code
    */
    function generateAddToParent($code) {
        $code->writePHP('$this->appendChild(');
        $this->generateInstantiation($code);
        $code->writePHP(', \'' . $this->getViewId() . '\');' . "\n"); // use var_export
    }

    /**
    * Template method for generating paramater code that should appear in the parent::__construct() call
    * @param Wact_Php_Writer $code
    */
    function generateConstructParameters($code) {
    }

    /**
    * Template method for generating code that should appear in the __construct method
    * @param Wact_Php_Writer $code
    */
    function generateConstruct($code) {
    }

    /**
    * Render the constructor code
    * @param Wact_Php_Writer $code
    */
    function generateConstructMethod($code) {
        // generate this code into our parent's scope
        if ($this->parent) {
            $this->generateAddToParent($code);
        }

        $oldScope = $code->createClass($this->getViewClass(), $this->parentViewClass);

        $code->createMethod('__construct');

        $this->generateConstruct($code);
        
        // Render child constructors
        $this->generateChildConstructMethods($code);
        
        // Call Wact_View_Partials constructor to run the setup() method provided by the user.
        // We call it after adding any children so that they are available during setup().
        $code->writePHP('parent::__construct(');
        $this->generateConstructParameters($code);
        $code->writePHP(');');

        if ($this->isPaintRequired()) {
            $code->writePHP('$this->lockChildren();');
        }
        
        $code->setScope($oldScope);
    }

    /**
    * Does this component desire to generate code into its own paint method?
    */
    function isPaintRequired() {
        foreach($this->children as $child) {
            if ($child->isInlinePaintRequired()) {
                return TRUE;
            }
        }
        return FALSE;
    }

    /**
    * @param Wact_Php_Writer $code
    */
    function generateInlineRenderCall($code) {
        $code->writePHP('$this->children[\'' . $this->getViewId() . '\']->render();');
    }

    /**
    * Pre generation method
    * @param Wact_Php_Writer $code
    * @return void
    */
    function generatePrePaint($code) {
    }

    /**
    * Post generation method
    * @param Wact_Php_Writer $code
    * @return void
    */
    function generatePostPaint($code) {
    }

    /**
    * @param Wact_Php_Writer $code
    */
    function generateExtraMethods($code) {
    }

    /**
    * @param Wact_Php_Writer $code
    */
    function generatePaintMethod($code) {

        if ($this->isPaintRequired()) {
            $oldScope = $code->switchToClassScope($this->getViewClass());
            $code->createMethod('paint');
        
            $this->generatePrePaint($code);
            $this->generateChildPaintInline($code);
            $this->generatePostPaint($code);

            $code->setScope($oldScope);
        } else {
            $this->generateChildPaintMethods($code);
        }
        $this->generateExtraMethods($code);
    }

    /**
    * @param Wact_Php_Writer $code
    */
    function generatePaintInline($code) {
        $this->generateInlineRenderCall($code);
        $this->generatePaintMethod($code);
    }
    
}
?>