<?php
/**
 * A class for rendering the presentation layer.
 *
 * This class provides a way to gather template variables and render template
 * files. It is also adaptable to various types of templates (native php,
 * twig, pdf, etc.).
 */
class view
{
    /**
     * @var view_renderer The renderer.
     */
    protected $renderer;
    
    /**
     * @var array The template variables.
     */
    protected $data;

    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.

    /**
     * @param view_renderer (optional) $renderer The renderer.
     */
    public function __construct(view_renderer $renderer = null)
    {
        $this->renderer = $renderer;
        $this->clear();
    }

    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    /**
     * A shortcut for set().
     * 
     * @param string $name The variable name.
     * @param mixed $value The value.
     */
    public function __set($name, $value)
    {
        $this->set($name, $value);
    }

    /**
     * A shortcut for clear().
     * 
     * @param string $name The variable name.
     */
    public function __unset($name)
    {
        $this->clear($name);
    }

    /**
     * A shortcut for using a view widget class.
     * 
     * @param string $function The class name.
     * @param array $parameter The parameters.
     * @return string The rendered widget.
     */
    public static function __callstatic($function, array $parameter)
    {
        return call_user_func_array('view_widget_' . $function . '::render', $parameter);
    }

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.

    /**
     * Renders a template.
     * 
     * @param string/array $template The template(s).
     * @param array (optional) $data The template variables.
     * @return string The rendered template.
     */
    public function render($template, array $data = array())
    {
        if (!$this->renderer)
        {
            $this->renderer = new view_renderer_composite;
        }
        
        $merged = $this->data;
        
        foreach ($data as $k => $v)
        {
            $merged[$k] = $v;
        }
        
        return $this->renderer->render($template, $merged);
    }

    /**
     * Sets one or more template variables.
     * 
     * @param string $name The variable name.
     * @param mixed $value The value.
     * -
     * @param array $name The variables.
     * @return view A fluent interface.
     */
    public function set($name, $value = null)
    {
        if (is_array($name))
        {
            foreach ($name as $k => $v)
            {
                $this->data[$k] = $v;
            }
        }
        else
        {
            $this->data[$name] = $value;
        }
        
        return $this;
    }

    /**
     * Clears one or all template variables.
     * 
     * @param string (optional) $name The variable name.
     * @return view A fluent interface.
     */
    public function clear($name = null)
    {
        if ($name === null)
        {
            $this->data = array();
        }
        else
        {
            unset($this->data[$name]);
        }
        
        return $this;
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
}
