<?php

/**
 * Goweb Sitemanager 5 Framework
 *
 * Ficheiro de metodos comuns 
 *
 * @version    5.0.15
 * @category   Goweb
 * @package    Goweb_Js
 * @subpackage Tree
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */

/**
 * Goweb_Js_Tree_Node
 */
Goweb::loadClass('Goweb_Js_Tree_Node');

/**
 * Classe para gerar o javascript do dtree
 *
 * @version    5.0.15
 * @category   Goweb
 * @package    Goweb_Js
 * @subpackage Tree
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */
class Goweb_Js_Tree {

    /**
     * Nome da variável da tree
     * 
     * @var  string
     */
    protected $_name = '';

    /**
     * Valor da tree no caso de haver um formul&aacute;rio
     * 
     * @var  string
     */
    protected $_value = null;

    /**
     * Array com os nodes
     * 
     * @var  array
     */
    protected $_nodes = array();

    /**
     * Array com os paremetros
     * 
     * @var  array  
     */
    protected $_params = array();

    /**
     * Titulo da tree
     * 
     * @var  string
     */
    protected $_title = '';
    
    /**
     * ID do node a abrir
     * 
     * @var  int
     */
    protected $_openTo = null;

    /**
     * Expandir ervore
     * 
     * @var  bool
     */
    protected $_expand = false;
    
    /**
     * Constructor
     *
     * Paremetros:
     * <code>
     * target         => (string) O <i>target</i> para todos os nodes
     * folderLinks    => (boolean) Os <i>folders</i> podem se links
     * useSelection   => (boolean) Os <i>nodes</i> podem se seleccionados(highlighted)
     * useCookies     => (boolean) Usar cookies para lembrar o estado da tree
     * useLines       => (boolean) Usar linhas
     * useIcons       => (boolean) Usar icons
     * useStatusText  => (boolean) Mostrar nomes na statusbar
     * closeSameLevel => (boolean) Fechar no mesmo nivel
     * inOrder        => (boolean) Os <i>node</i> pais sco adicionado antes dos filhos
     * </code>
     *
     * @param  string  $name  Nome
     */
    public function __construct($name, $value = null) {
        $this->_name = $name;
        $this->_value = $value;
        $this->_params = array('target'         => null,
                               'folderLinks'    => true,
                               'useSelection'   => true,
                               'useCookies'     => true,
                               'useLines'       => true,
                               'useIcons'       => true,
                               'useStatusText'  => false,
                               'closeSameLevel' => false,
                               'inOrder'        => false);
    }

    /**
     * Adiciona um objecto do tipo node.
     * 
     * @param  Goweb_Js_Tree_Node  $node  O objecto node
     */
    public function addNode(Goweb_Js_Tree_Node $node) {
        $this->_nodes[] = $node;
    }

    /**
     * Atribui o titulo e tree.
     * 
     * @param  string  $title  O titulo da tree
     */
    public function setTitle($title) {
        $this->_title = $title;
    }
    
    /**
     * Atribui um valor e tree.
     * 
     * @param  string  $value  Valor
     */
    public function setValue($value) {
        $this->_value = $value;
    }
    
    /**
     * Atribui o ID do node a abrir.
     * 
     * @param  int      $id        O ID do node
     */
    public function setOpenTo($id) {
        $this->_openTo = $id;
    }
    
    /**
     * Abre um node.
     * 
     * @param  int      $id        O ID do node
     * @param  boolean  $selected  TRUE para seleccionar o node
     */
    public function openTo($id, $selected = true) {
        return $this->_name . ".openTo('" . $id . "'," . $this->_booleanToString($selected) . ");\n";
    }

    /**
     * Define se e para expandir a ervore
     * 
     * @param  boolean  $expand  TRUE para expandir
     */
    public function setExpand($expand) {
        $this->_expand = $expand;
    }

    /**
     * Efectua o redering e retorna o ouput do javascript.
     *
     * @return  string  O output do javascript
     */
    public function render($expand = false) {
        $output  = "<script type=\"text/javascript\">\n";
        $output .= "<!--\n";
        $output .= $this->_name . " = new dTree('" . $this->_name . "'" . ($this->_value ? (",'" . $this->_value . "'") : "") . ");\n";
        $output .= $this->_name . ".config.folderLinks=" . $this->_booleanToString($this->_params['folderLinks']) . ";\n";
        $output .= $this->_name . ".config.useSelection=" . $this->_booleanToString($this->_params['useSelection']) . ";\n";
        $output .= $this->_name . ".config.useCookies=" . $this->_booleanToString($this->_params['useCookies']) . ";\n";
        $output .= $this->_name . ".config.useLines=" . $this->_booleanToString($this->_params['useLines']) . ";\n";
        $output .= $this->_name . ".config.useIcons=" . $this->_booleanToString($this->_params['useIcons']) . ";\n";        
        $output .= $this->_name . ".config.useStatusText=" . $this->_booleanToString($this->_params['useStatusText']) . ";\n";
        $output .= $this->_name . ".config.closeSameLevel=" . $this->_booleanToString($this->_params['closeSameLevel']) . ";\n";
        $output .= $this->_name . ".config.inOrder=" . $this->_booleanToString($this->_params['inOrder']) . ";\n";        
        foreach ($this->_nodes as $node) {
            $output .= $this->_name.".add('";
            $params = $node->getParams();
            
            if (array_key_exists('name', $params)) {
                $params['name'] = str_replace("\\", "", $params['name']);
                $params['name'] = str_replace("\\'", "'", $params['name']);
                $params['name'] = str_replace("\'", "'", $params['name']);
                $params['name'] = str_replace("'", "\'", $params['name']);
            }
            
            unset($params['urlId']);
            $output .= implode("','", $params);
            $output .= "');\n";
        }
        
        $output .= "document.write(" . $this->_name .");\n";
        if ($this->_openTo) {
            $output .= $this->openTo($this->_openTo);
        } else {
            $output .= $this->openTo('0');
        }
        if ($expand || $this->_expand) {
            $output .= $this->_name . ".openAll();\n";
        }
        $output .= "-->\n";
	$output .= "</script>\n";
        return $output;
    }

    /**
     * Retorna o link para abrir todos os nodes
     *
     * @return  string
     */
    public function openAllLink() {
        return 'javascript:' . $this->_name . '.openAll();';
    }

    /**
     * Retorna o link para fechar todos os nodes
     *
     * @return  string
     */
    public function closeAllLink() {
        return 'javascript:' . $this->_name . '.closeAll();';
    }

    /**
     * Retorna o titulo da tree.
    */
    public function getTitle() {
        return $this->_title;        
    }
    
    /**
     * Transforma um campo boleano numa string
     * 
     * @return  string
     */
    protected function _booleanToString($value) {
        return ($value) ? 'true' : 'false';
    }
    
    /**
     * Atribui um valor ao paremetro
     * 
     * @param   string  O nome do paremetro
     * @param   mixed   O valor do paremetro
     * @throws  Goweb_Exception  No caso do paremetro n&atilde;o existir
     */
    public function __set($key, $value) {
        if (!array_key_exists($key, $this->_params)) {
            throw new Goweb_Exception("O paremetro '$key' n&atilde;o existe na classe '" . get_class($this) . "'");
        }
        $this->_params[$key] = $value;
    }

    /**
     * Retorna o valor de um paremetro
     * 
     * @param   string  O nome do paremetro
     * @throws  Goweb_Exception  No caso do paremetro n&atilde;o existir
     * @return  mixed   O valor do paremetro
     */
    public function __get($key) {
        if (!array_key_exists($key, $this->_params)) {
            throw new Goweb_Exception("O paremetro '$key' n&atilde;o existe na classe '" . get_class($this) . "'");
        }
        return $this->_params[$key];
    }
}
