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

/**
* Provides an API for generating PHP code blocks.
* This class can start out either in PHP or HTML context
* thus takes care of necessary PHP tags.
* Set your initial context with the constructor.
*/
class Wact_Php_Writer_Block {

    const MODE_PHP = 1;
    const MODE_HTML = 2;

    /**
    * String containing the generated code
    * @var string
    */
    protected $code = '';

    /**
    * The current state of the writer.
    * @var int (self::MODE_PHP or self::MODE_HTML);
    */
    protected $mode = null;

    /**
    * The initial state of the writer.
    * @var int (self::MODE_PHP or self::MODE_HTML);
    */
    protected $defaultMode = null;

    /**
    * Count of the current number of temporary variables in the block
    * @var int
    */
    protected $tempVariableCount = 1;

    /**
    * Class constructor
    * @param int $mode self::MODE_PHP or self::MODE_HTML
    */
    public function __construct($mode) {
        $this->mode = $mode;
        $this->defaultMode = $mode;
    }

    /**
    * Puts the writer into PHP mode, writing an opening PHP processing
    * instruction to the code. Does nothing if writer is already
    * in PHP mode
    */
    public function switchToPHP() {
        if ($this->mode == self::MODE_HTML) {
            $this->mode = self::MODE_PHP;
            $this->code .= '<?' . 'php ';
        }
    }

    /**
    * Puts the writer into HTML mode, writing a closing PHP processing
    * instruction to the code. Does nothing if writer is already in
    * HTML mode
    */
    public function switchToHTML($context = NULL) {
        if ($this->mode == self::MODE_PHP) {
            $this->mode = self::MODE_HTML;
            if ($context === "\n") {
                $this->code .= " ?" . ">\n";
            } else {
                $this->code .= ' ?' . '>';
            }
        }
    }

    /**
    * Writes some PHP to the code
    * @param string PHP to write
    */
    public function writePHP($text) {
        $this->switchToPHP();
        $this->code .= $text;
    }

    /**
    * Writes PHP Literal String.  Makes sure that escape characters are
    * proper for source code escaping of string literal.
    * @param mixed value PHP to write
    */
    public function writePHPLiteral($value) {
        $this->switchToPHP();
        $this->code .= var_export($value, TRUE);
    }

    /**
    * Writes some HTML to the code
    * @param string HTML to write
    */
    public function writeHTML($text) {
        $this->switchToHTML(substr($text,0,1));
        $this->code .= $text;
    }

    /**
    * Returns the finished block code.
    * Keeps the initial context (PHP/HTML). PHP tags are added where necessary.
    * @return string
    */
    public function getBlockCode() {
        switch ($this->defaultMode) {
            case self::MODE_PHP:
                $this->switchToPHP();
                break;
            case self::MODE_HTML:
                $this->switchToHTML();
                break;
        }

        return $this->code;
    }

    /**
    * Returns the include code + the finished block code.
    * Keeps the initial context (PHP/HTML). PHP tags are added where necessary.
    * @return string
    */
    public function getCode() {
        return $this->getBlockCode();
    }

    /**
    * Utility method, which generates a unique variable name
    * for custom use within the block.
    * @return string Temp variable name. You need to apply the appropriate prefix ('$'/'$this->' etc.) manually if needed.
    */
    public function createTempVariable() {
        $cnt = $this->tempVariableCount++;
        if ($cnt > 675) {
            $var = chr(65 + ($cnt/26)/26) . chr(65 + ($cnt/26)%26) . chr(65 + $cnt%26);
        } elseif ($cnt > 26) {
            $var = chr(65 + ($cnt/26)%26) . chr(65 + $cnt%26);
        } else {
            $var = chr(64 + $cnt);
        }

        return $var;
    }

    /**
    */
    public function getClassName() {
        return NULL;
    }

    /**
    */
    public function getMethodName() {
        return NULL;
    }

    /**
    */
    public function getFunctionName() {
        return NULL;
    }

    /**
    * Undefined Operation
    */
    public function findMethod($name) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function registerMethod(Wact_Php_Writer_Method $method) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function createMethod($name, $params = null) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function createTempProperty() {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function registerProperty($property) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function createProperty($name, $value = null, $visibility = 'public') {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function findProperty($name) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function propertyExists($name) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

    /**
    * Undefined Operation
    */
    public function switchToMethodScope($name) {
        throw new Wact_Php_Writer_Exception('Invalid scope');
    }

}

?>