<?php

Goweb::loadClass('Goweb_Form');

/**
 * Goweb Sitemanager 5 Framework
 * @version    5.1.4
 * @category   Backoffice
 * @package    Index
 * @subpackage Form
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2010 (c) Goweb (http://www.goweb.pt)
*/
class Goweb_Form_Generic extends Goweb_Form {
    
    /**
     * Nome da seccao
     *
     * @var string
    */
    protected $_sectionName;
    
    /**
     * Array com os labels do model
     *
     * @var array
    */
    protected $_labels;
    
    /**
     * Objecto Goweb_Db_Model
     * @var Goweb_Db_Model
    */
    protected $_model;

    /**
     * Objecto Goweb_Request
     * @var Goweb_Request
    */
    protected $_request;
    
    /**
     * campos para o autocomplete
     *
     * @var array
     */
    protected $_autocomplete = array();
    
    public function getAutoCompletes(){
        return  $this->_autocomplete;
    }
    
    /**
     * Este metodo eh utilizado na construcao generica dos
     * modulos automaticos
     *
     * @param string
     * @param array
     * @param Goweb_Db_Model
     * @param integer
     * @param integer
    */
    public function setup($sectionName, $labels, $model, $parent = null, $parent_id = 0) {
        $this->_request = Zend_Controller_Front::getInstance()->getRequest();
        $this->_sectionName = $sectionName;
        $this->_labels = $labels;
        $this->_model = $model;
        $label = '';
        foreach ($this->_model->getCols() as $colName => $col) {
            if (array_key_exists($colName, $this->_labels) && strlen($this->_labels[$colName])) {
                $label = $this->_labels[$colName];
            } else {
                $label = $this->_formatNameForLabel($colName);
            }
            if ($col->getParam('show') === false) {
                continue;
            }
            if ($col->getParam('show')) {
                switch ($col->getType()) {
                 case 'ForeignKeyMultiple':
                         $treeValue = $model->{$colName} && strpos($model->{$colName}, 'a:') === 0 ? unserialize($model->{$colName}) : array();
                         $element = $col->getParam('form');
                         if (strtolower($element) == 'tree'){
                             Goweb::loadClass('Goweb_Js_Tree');
                             Goweb::loadClass('Goweb_Js_Tree_Node');
                         } else {
                             $options = array();
                         }
                         $foreignModelName = $col->getParam('model');
                         $foreignModel = Goweb::getModelInstance($foreignModelName, $this->_model->getAdapter(), false, true);
                         if (strtolower($element) == 'tree'){
                             $tree = new Goweb_Js_Tree($colName);
                             $tree->useSelection = false;
                             $tree->setExpand(false);
                             $node = new Goweb_Js_Tree_Node(0, -1, translateAdmin('Raiz'));
                             $tree->addNode($node);
                         }
                         if ($col->getParam('order')) {
                             $foreignModel->order($col->getParam('order'));
                         }

                         if ($col->getParam('where')) {
                             if (is_string($col->getParam('where')) && method_exists($foreignModel, $col->getParam('where'))) {
                                 $foreignModel->where(call_user_func(array($foreignModel, $col->getParam('where'))));
                             } else {
                                 $foreignModel->where($col->getParam('where'));
                             }
                         }
                         $rowset = $foreignModel->fetchAll();
                         if ($rowset) {
                             foreach ($rowset as $row){
                                 $rowTitulo = $row->{$foreignModel->getToString()};
                                 if (strtolower($element) == 'tree'){
                                     $node = new Goweb_Js_Tree_Node($row->{$foreignModel->getPrimary()}, $foreignModel->colExists('pai_id') ? $row->pai_id: 0, $rowTitulo);
                                     $node->form_element = 'checkbox';
                                     if (in_array($row->{$foreignModel->getPrimary()}, $treeValue)) {
                                         $node->form_checked = true;
                                     }
                                     $tree->addNode($node);
                                 } else {
                                     $options[$row->{$foreignModel->getPrimary()}] = $rowTitulo;
                                 }
                             }
                         }
                         if (strtolower($element) == 'tree'){
                             $this->{$colName} = $this->Tree();
                             $this->{$colName}->tree = $tree;
                             $this->{$colName}->expand = false;
                         } else {
                             $this->{$colName} = $this->{$element}();
                             $this->{$colName}->options = $options; 
                             $this->{$colName}->multiple = true;
                             if ($col->getParam('update')){
                                 $campos = $col->getParam('update');
                                 $updateCol = $col->getParam('updateCol');
                                 if (!$updateCol){
                                     $updateCol = $colName;
                                 }
                                 if (is_array($campos)){
                                     $onChange = "";
                                     foreach ($campos as $campo){
                                         if (!$model->colExists($campo)){
                                             throw new Goweb_Exception("O campo '$campo' nao existe no model '" . get_class($model) . "'");
                                         }
                                         Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                         $onChange .= 'gowebUpdateSelect("' . str_replace('/admin', '', Goweb::link('/index/gowebUpdateSelect/')) . '","' . get_class($model) . '", "' . $updateCol . '", "' . $campo . '", $(this).getValue());';
                                     }
                                 } else {
                                     if (!$model->colExists($campos)){
                                         throw new Goweb_Exception("O campo '$campos' nao existe no model '" . get_class($model) . "'");
                                     }
                                     Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                     $onChange = 'gowebUpdateSelect("' . str_replace('/admin', '', Goweb::link('/index/gowebUpdateSelect/')) . '","' . get_class($model) . '", "' . $updateCol . '", "' . $campos . '", $(this).getValue());';
                                 }

                                 $this->{$colName}->setAttrib('onchange', $onChange);
                             }
                         }
                         $this->{$colName}->label = $label;
                         
                     break;
                    case 'ForeignKey':
                        $element = $col->getParam('form');
                        $this->{$colName} = $this->{$element}();
                        $this->{$colName}->label = $label;

                        $foreignModelName = $col->getParam('model');
                        $foreignModel = Goweb::getModelInstance($foreignModelName, $this->_model->getAdapter(), false, true);

                        if (!$model->isLoaded() && $parent == $colName && $parent_id) {
                            $this->{$colName}->value = $parent_id;
                        } elseif ($model->isLoaded()) {
                            $this->{$colName}->value = strpos($model->{$colName}, 'a:') === 0 ? unserialize($model->{$colName}) : $model->{$colName};
                        }

                        $options = array();
                        if (strtolower($col->getParam('form')) == 'select'){
                            $options[$col->getParam('default')] = html_entity_decode(translate('Escolha uma op&ccedil;&atilde;o'), ENT_NOQUOTES, CHARSET);
                        }

                        if ($col->getParam('order')) {
                            $foreignModel->order($col->getParam('order'));
                        }

                        if ($col->getParam('where')) {
                            if (is_string($col->getParam('where')) && method_exists($foreignModel, $col->getParam('where'))) {
                                $foreignModel->where(call_user_func(array($foreignModel, $col->getParam('where'))));
                            } else {
                                $foreignModel->where($col->getParam('where'));
                            }
                        }

                        $rowset = $foreignModel->fetchAll();
                        if ($rowset) {
                            $key = $foreignModel->getPrimary();
                            $label = $foreignModel->getToString();
                            if (!strlen($label)) {
                                $label = $key;
                            }
                            foreach ($rowset as $row) {
                                $options[$row->{$key}] = html_entity_decode($row->{$label}, ENT_NOQUOTES, CHARSET);
                            }
                            if ($foreignModel->colExists('pai_id')){
                                $this->{$colName . '_tafel'} = $this->Button();
                                $this->{$colName . '_tafel'}->label = '<span>' . translate("Alterar {{campo}}", strip_tags($this->{$colName}->label)) . '</span>';
                                $this->{$colName . '_tafel'}->setAttrib('onclick', 'gowebShowModalBox("' . str_replace('/admin', '', Goweb::link('/index/treeSelect/')) . '?model=' . $foreignModelName . '&amp;col=' . $colName .'", "'.strip_tags($this->{$colName}->label).'");');
                                $this->{$colName . '_tafel'}->setAttrib('class', 'submitBtn');
                                $this->{$colName . '_tafel'}->setAttrib('escape', false);
                                Goweb::loadJavascript('/admin/media/js/prototype.js');
                                Goweb::loadJavascript('/admin/media/js/scriptaculous/scriptaculous.js');
                                Goweb::loadJavascript('/admin/media/js/scriptaculous/effects.js');
                                Goweb::loadJavascript('/admin/media/js/modalbox.js');
                                Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                Goweb::loadCss('/admin/media/css/modalbox.css');
                                Goweb::loadCss('/admin/media/js/tafelTree/css/tree.css');
                                Goweb::loadJavascript('/admin/media/js/tafelTree/Tree-optimized.js');
                            }

                        }


                        $this->{$colName}->options = $options;

                        if ($col->getParam('update')){
                            $campos = $col->getParam('update');
                            $updateCol = $col->getParam('updateCol');
                            if (!$updateCol){
                                $updateCol = $colName;
                            }
                            if (is_array($campos)){
                                $onChange = "";
                                Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                foreach ($campos as $campo){
                                    if (!$model->colExists($campo)){
                                        throw new Goweb_Exception("O campo '$campo' nao existe no model '" . get_class($model) . "'");
                                    }
                                    Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                    $onChange .= 'gowebUpdateSelect("' . str_replace('/admin', '', Goweb::link('/index/gowebUpdateSelect/')) . '","' . get_class($model) . '", "' . $updateCol . '", "' . $campo . '", $(this).getValue());';
                                }
                            } else {
                                if (!$model->colExists($campos)){
                                    throw new Goweb_Exception("O campo '$campos' nao existe no model '" . get_class($model) . "'");
                                }
                                Goweb::loadJavascript('/media/js/goweb_ajax.js');
                                $onChange = 'gowebUpdateSelect("' . str_replace('/admin', '', Goweb::link('/index/gowebUpdateSelect/')) . '","' . get_class($model) . '", "' . $updateCol . '", "' . $campos . '", $(this).getValue());';
                            }

                            $this->{$colName}->setAttrib('onchange', $onChange);
                        }

                        if ($col->getParam('notnull'))
                        $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                        //}
                        $this->{$colName}->error_class = 'error';
                        $this->{$colName}->focus_class = 'focus';
                        break;
                         
                 case 'SelfKey':
                     $this->{$colName} = $this->Select();
                     $this->{$colName}->label = $label;                 
                     $foreignModelName = $col->getParam('model');
                     $foreignModel = Goweb::getModelInstance(get_class($model), $this->_model->getAdapter(), false, false);
                     
                     if ($col->getParam('where')) {
                         if (is_string($col->getParam('where')) && method_exists($foreignModel, $col->getParam('where'))) {
                             $foreignModel->where(call_user_func(array($foreignModel, $col->getParam('where'))));
                         } else {
                             $foreignModel->where($col->getParam('where'));
                         }
                     }
                     if ($model->isLoaded()) {
                         $foreignModel->where($model->getTableName() . '.' .$model->getPrimary() . '<>' .  $model->{$model->getPrimary()});
                         $this->{$colName}->value = $model->{$colName};
                     } elseif ($parent == $colName && $parent_id) {                     
                         $this->{$colName}->value = $parent_id;                     
                     }
                 
                     $options = array();
                     $options[$col->getParam('default')] = html_entity_decode(translate('Escolha uma op&ccedil;&atilde;o'), ENT_NOQUOTES, CHARSET);
                     $rowset = $foreignModel->fetchAll();
                     if ($rowset) {
                         $key = $foreignModel->getPrimary();
                         $label = $foreignModel->getToString();
                         if (!strlen($label)) {
                             $label = $key;
                         }
                         foreach ($rowset as $row) {
                             $options[$row->{$key}] = html_entity_decode($row->{$label}, ENT_NOQUOTES, CHARSET);
                         }
                         if ($foreignModel->colExists('pai_id')){
                            $this->{$colName . '_tafel'} = $this->Button();
                            $this->{$colName . '_tafel'}->label = '<span>' . translate("Alterar {{campo}}", strip_tags($this->{$colName}->label)) . '</span>';
                            $this->{$colName . '_tafel'}->setAttrib('onclick', 'gowebShowModalBox("' . str_replace('/admin', '', Goweb::link('/index/treeSelect/')) . '?model=' . get_class($foreignModel) . '&amp;col=' . $colName .'", "'.strip_tags($this->{$colName}->label).'"' . ($col->getParam('filter') ? ', "'. $col->getParam('filter') .'"' : '') . ');');
                            $this->{$colName . '_tafel'}->setAttrib('class', 'submitBtn');
                            $this->{$colName . '_tafel'}->setAttrib('escape', false);
                            Goweb::loadJavascript('/admin/media/js/prototype.js');
                            Goweb::loadJavascript('/admin/media/js/scriptaculous/scriptaculous.js');
                            Goweb::loadJavascript('/admin/media/js/scriptaculous/effects.js');
                            Goweb::loadJavascript('/admin/media/js/modalbox.js');
                            Goweb::loadJavascript('/media/js/goweb_ajax.js');
                            Goweb::loadCss('/admin/media/css/modalbox.css');
                            Goweb::loadCss('/admin/media/js/tafelTree/css/tree.css');
                            Goweb::loadJavascript('/admin/media/js/tafelTree/Tree-optimized.js');
                         }
                         
                     }
                     
                     $this->{$colName}->options = $options;
                     if ($col->getParam('notnull'))
                     $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                                          
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';                 
                     break;
                     
                 case 'SelectFill':
                     $this->{$colName} = $this->SelectFill();
                     $this->{$colName}->label = $label;
                     
                     // nome do model filho
                     $this->{$colName}->child  = $col->getParam('child');
                     
                     // nome do campo do neto
                     $this->{$colName}->grandchild  = $col->getParam('grandchild');
                     
                     // nome do campo do pai
                     $this->{$colName}->parent = $col->getParam('parent');
                     
                     $foreignModelName = $col->getParam('model');
                     $foreignModel     = Goweb::getModelInstance($foreignModelName,
                                                                 $this->_model->getAdapter(),
                                                                 false,
                                                                 true);
                     
                     if (!$model->isLoaded() && $parent == $colName && $parent_id) {
                         $this->{$colName}->value = $parent_id;
                     } elseif ($model->isLoaded()) {
                         $this->{$colName}->value = $model->{$colName};
                     }
                     
                     if ($col->getParam('order')) {
                         $foreignModel->order($col->getParam('order'));
                     }
                     
                     $options = array();
                     
                     if (!$col->getParam('parent')) {
                         $options[$col->getParam('default')] = html_entity_decode(translate('Escolha uma op&ccedil;&atilde;o'), ENT_NOQUOTES, CHARSET);
                         
                         $rowset = $foreignModel->fetchAll();                 
                         if ($rowset) {
                             $key = $foreignModel->getPrimary();
                             $label = $foreignModel->getToString();
                             if (!strlen($label)) {
                                 $label = $key;
                             }
                             foreach ($rowset as $row) {
                                 $options[$row->{$key}] = $row->{$label};
                             }
                         }
                     } else {
                         $rowset = $foreignModel->fetchAll();
                         if ($rowset) {
                             $key = $foreignModel->getPrimary();
                             $label = $foreignModel->getToString();
                             $parent = $col->getParam('parent');
                             if (!strlen($label)) {
                                 $label = $key;
                             }
                             if ($model->isLoaded()) {
                                 foreach ($rowset as $row) {
                                     $options[$row->{$parent}][$row->{$key}] = array('nome' => $row->{$label},
                                                                                     'parentValue' => $model->{$col->getParam('parent')});
                                 }
                             } else {
                                 foreach ($rowset as $row) {
                                     $options[$row->{$parent}][$row->{$key}] = array('nome' => $row->{$label},
                                                                                     'parentValue' => '');
                                 }
                             }
                         }
                     }
                     $this->{$colName}->options = $options;
                     if ($col->getParam('notnull'))
                     $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                      
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                     
                 case 'Char':
                     if ($col->getParam('options')) {
                         $element = $col->getParam('form');
                         $this->{$colName} = $this->{$element}();
                         $this->{$colName}->options = $col->getParam('options');
                         if (in_array($col->getParam('form'), array('DynamicOptions'))){
                             $this->{$colName}->defaults = $col->getParam('defaults');
                             $this->{$colName}->subFormType = $col->getParam('subFormType');
                             $this->{$colName}->grupos = $col->getParam('grupos');
                         }
                     } else {
                         $this->{$colName} = $this->Text();
                         $this->{$colName}->size = $col->getParam('size');
                         $this->{$colName}->maxlength = $col->getParam('maxlength');                         
                     }
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     
                     if ($col->getParam('auto_complete')) {
                         $autoComplete = $col->getParam('auto_complete');
                         if ($autoComplete['type'] == 'Local'){
                             $foreignModelName = $autoComplete['model'];
                             $foreignModel     = Goweb::getModelInstance($foreignModelName,
                                                                         $this->_model->getAdapter(),
                                                                         false,
                                                                         true);
                              
                             if ($autoComplete['where']) {
                                 $foreignModel->order($autoComplete['where']);
                             }
                             if ($autoComplete['order']) {
                                 $foreignModel->order($autoComplete['order']);
                             }
                             if ($autoComplete['campo']){
                                 $campo = $autoComplete['campo'];
                             } else {
                                 $campo = $foreignModel->getToString();
                             }
                             $foreignModel->distinct();
                             $rowset = $foreignModel->fetchAll(array($campo));
                             if ($rowset) {
                                 $output = '';
    
                                 foreach ($rowset as $row) {
                                     $output .= '"'.html_entity_decode($row->{$campo}, ENT_COMPAT, CHARSET) . '", ';
                                 }
                                 $output = substr($output, 0, -2);
                                 $this->_autocomplete[$colName] = '
                                 new Autocompleter.Local(\'' . $colName . '\',
                                  \'' . $colName . '_update\',
                                  new Array('. $output .'),
                                            { tokens: new Array(\',\', \';\', \'\n\'), fullSearch: ' . ($autoComplete['fullSearch'] ? 'true' : 'false') . ', partialSearch: ' . ($autoComplete['partialSearch'] ? 'true' : 'false') . ', ignoreCase: ' . ($autoComplete['ignoreCase'] ? 'true' : 'false') . ($autoComplete['partialChars'] && is_numeric($autoComplete['partialChars']) ? ', partialChars: ' .  $autoComplete['partialChars'] : '') . ($autoComplete['choices'] && is_numeric($autoComplete['choices']) && $autoComplete['choices'] > 0 ? ', choices: ' .  $autoComplete['choices'] : '') . ' });';
    
                                  
                             }
                         } else if ($autoComplete['type'] == 'Ajax'){
                                $this->_autocomplete[$colName] = '
                                 new Ajax.Autocompleter(\'' . $colName . '\',
                                  \'' . $colName . '_update\', 
                                  \'' . str_replace('/admin', '', Goweb::link('/index/ajaxAutocomplete/')) . '?model=' . get_class($this->_model) . '&col=' . $colName. '\',
                                  {
                                  fullSearch: ' . ($autoComplete['fullSearch'] ? 'true' : 'false') . ', 
                                  partialSearch: ' . ($autoComplete['partialSearch'] ? 'true' : 'false') . ', 
                                  ignoreCase: ' . ($autoComplete['ignoreCase'] ? 'true' : 'false') . ',
                                  minChars: ' . ($autoComplete['minChars'] && is_numeric($autoComplete['minChars']) && $autoComplete['minChars'] > 0 ? $autoComplete['minChars'] : '3') .  
                                  ($autoComplete['partialChars'] && is_numeric($autoComplete['partialChars']) ? ', ' . "\n" . ' partialChars: ' .  $autoComplete['partialChars'] : '') .                                
                                  ($autoComplete['choices'] && is_numeric($autoComplete['choices']) && $autoComplete['choices'] > 0 ? ', ' . "\n" . ' choices: ' .  $autoComplete['choices'] : '') . 
                                  "\n" . ' });';
                         } else {
                             throw new Goweb_Exception($autoComplete['type'] . ' not implemented');
                         }
                     }
                     
                     break;
                 
                 case 'ColorPicker':
                     
                     $element = $col->getParam('form');
                     $this->{$colName} = $this->{$element}();
                     $this->{$colName}->options = $col->getParam('options');
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                 
                     
                 case 'Text':
                     if ($col->getParam('form') == 'Rte') {
                         $this->{$colName} = $this->Rte();
                         $this->{$colName}->theme = $col->getParam('theme');
                         $this->{$colName}->css = $col->getParam('css');
                         $this->{$colName}->width = $col->getParam('width');
                         $this->{$colName}->height = $col->getParam('height');
                     } else {
                         $this->{$colName} = $this->Textarea();
                         $this->{$colName}->cols = $col->getParam('cols');
                         $this->{$colName}->rows = $col->getParam('rows');                         
                     }                     
                     
                     if (array_key_exists($colName, $this->_labels)) {
                         $this->{$colName}->label = $this->_labels[$colName];
                     } else {
                         $this->{$colName}->label = $colName;
                     }
                     
                     /**
                      * maxlength não é suportado numa textarea de acordo com os standards
                      */
                     /*if ($col->getParam('maxlength') > 0 ) {
                         $this->{$colName}->maxlength = $col->getParam('maxlength');
                     }*/
                     if ($col->getParam('auto_complete')) {
                         $autoComplete = $col->getParam('auto_complete');
                         if ($autoComplete['type'] == 'Local'){
                             $foreignModelName = $autoComplete['model'];
                             $foreignModel     = Goweb::getModelInstance($foreignModelName,
                                                                         $this->_model->getAdapter(),
                                                                         false,
                                                                         true);
                              
                             if ($autoComplete['where']) {
                                 $foreignModel->order($autoComplete['where']);
                             }
                             if ($autoComplete['order']) {
                                 $foreignModel->order($autoComplete['order']);
                             }
                             if ($autoComplete['campo']){
                                 $campo = $autoComplete['campo'];
                             } else {
                                 $campo = $foreignModel->getToString();
                             }
                             $foreignModel->distinct();
                             $rowset = $foreignModel->fetchAll(array($campo));
                             if ($rowset) {
                                 $output = '';
    
                                 foreach ($rowset as $row) {
                                     $output .= '"'.html_entity_decode($row->{$campo}, ENT_COMPAT, CHARSET) . '", ';
                                 }
                                 $output = substr($output, 0, -2);
                                 $this->_autocomplete[$colName] = '
                                 new Autocompleter.Local(\'' . $colName . '\',
                                  \'' . $colName . '_update\',
                                  new Array('. $output .'),
                                            { tokens: new Array(\',\', \';\', \'\n\'), fullSearch: ' . ($autoComplete['fullSearch'] ? 'true' : 'false') . ', partialSearch: ' . ($autoComplete['partialSearch'] ? 'true' : 'false') . ', ignoreCase: ' . ($autoComplete['ignoreCase'] ? 'true' : 'false') . ($autoComplete['partialChars'] && is_numeric($autoComplete['partialChars']) ? ', partialChars: ' .  $autoComplete['partialChars'] : '') . ($autoComplete['choices'] && is_numeric($autoComplete['choices']) && $autoComplete['choices'] > 0 ? ', choices: ' .  $autoComplete['choices'] : '') . ' });';
    
                                  
                             }
                         } else if ($autoComplete['type'] == 'Ajax'){
                                $this->_autocomplete[$colName] = '
                                 new Ajax.Autocompleter(\'' . $colName . '\',
                                  \'' . $colName . '_update\', 
                                  \'' . str_replace('/admin', '', Goweb::link('/index/ajaxAutocomplete/')) . '?model=' . get_class($this->_model) . '&col=' . $colName. '\',
                                  {
                                  fullSearch: ' . ($autoComplete['fullSearch'] ? 'true' : 'false') . ', 
                                  partialSearch: ' . ($autoComplete['partialSearch'] ? 'true' : 'false') . ', 
                                  ignoreCase: ' . ($autoComplete['ignoreCase'] ? 'true' : 'false') . ',
                                  minChars: ' . ($autoComplete['minChars'] && is_numeric($autoComplete['minChars']) && $autoComplete['minChars'] > 0 ? $autoComplete['minChars'] : '3') .  
                                  ($autoComplete['partialChars'] && is_numeric($autoComplete['partialChars']) ? ', ' . "\n" . ' partialChars: ' .  $autoComplete['partialChars'] : '') .                                
                                  ($autoComplete['choices'] && is_numeric($autoComplete['choices']) && $autoComplete['choices'] > 0 ? ', ' . "\n" . ' choices: ' .  $autoComplete['choices'] : '') . 
                                  "\n" . ' });';
                         } else {
                             throw new Goweb_Exception($autoComplete['type'] . ' not implemented');
                         }
                     }

                     $this->{$colName}->label = $label;
                     $this->{$colName}->class = 'error';
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                     
                 case 'Password':
                     $this->{$colName} = $this->Password();
                     $this->{$colName . '_confirm'} = $this->Password();
                     $this->{$colName . '_confirm'}->label = translate('{{campo_password}} Confirma&ccedil;&atilde;o', $label);
                     $this->{$colName . '_confirm'}->error_class = 'error';
                     $this->{$colName . '_confirm'}->focus_class = 'focus';
                     
                     $this->{$colName . '_confirm'}->validators->SameAs(translate('O campo <b>{{campo}}</b> n&atilde;o coincide com <b>{{campo}} Confirma&ccedil;&atilde;o</b>', $label, $label),
                                                           array('element' => $colName));

                     $this->{$colName}->size = '20';
                     $this->{$colName}->maxlength = $col->getParam('maxlength');
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     if ($col->getParam('notnull') && $model->isLoaded()) {
                         $col->setParam('notnull', false);
                     }
                     break;
                                      
                 case 'Integer':
                     if ($colName != $this->_model->getPrimary()) {
                         if ($col->getParam('options')) {
                             $element = $col->getParam('form');
                             $this->{$colName} = $this->{$element}();
                             $this->{$colName}->options = $col->getParam('options');
                         } else {
                             $this->{$colName} = $this->Text();                     
                             $this->{$colName}->size = '10';
                             $this->{$colName}->maxlength = $col->getParam('maxlength');
                         }
                         $this->{$colName}->label = $label;
                         $this->{$colName}->error_class = 'error';
                         $this->{$colName}->focus_class = 'focus';
                         $this->{$colName}->validators->Integer(translate('O campo <b>{{campo}}</b> n&atilde;o &eacute; um n&uacute;mero inteiro.', $this->{$colName}->label));
                         $this->{$colName}->setAttrib('onkeypress', 'return restrictCharacters(this, event, digitsOnly);');
                     }
                     break;
                     
                 case 'SmallInteger':
                     if ($col->getParam('options')) {
                         $element = $col->getParam('form');
                         $this->{$colName} = $this->{$element}();
                         $this->{$colName}->options = $col->getParam('options');
                     } else {
                         $this->{$colName} = $this->Text();                     
                         $this->{$colName}->size = '10';
                         $this->{$colName}->maxlength = $col->getParam('maxlength');
                     }
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     $this->{$colName}->setAttrib('onkeypress', 'return restrictCharacters(this, event, digitsOnly);');
                     break;
                     
                 case 'Float':
                     $this->{$colName} = $this->Text();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->size = $col->getParam('max_digits') + $col->getParam('decimal_places') + 1;
                     $this->{$colName}->maxlength = $col->getParam('max_digits') + $col->getParam('decimal_places') + 1;
                     $this->{$colName}->validators->Float(translate('No campo <b>{{campo}}</b> tem de ser um campo decimal', $this->{$colName}->label),
                                                          array('max_digits'     => $col->getParam('max_digits'),
                                                                'decimal_places' => $col->getParam('decimal_places'),
                                                                'integer'        => $col->getParam('integer'),
                                                                'separator'      => '.'));
                     $this->{$colName}->setAttrib('onkeypress', 'return restrictCharacters(this, event, integerOnly);');
                     break;
                 case 'Date':
                     $this->{$colName} = $this->Date();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->maxlength = '10';
                     $this->{$colName}->size = '10';
                     $this->{$colName}->validators->Date(translate('No campo <b>{{campo}}</b> a data n&atilde;o &eacute; v&aacute;lida.', $this->{$colName}->label));
                     break;
                 
                 case 'Datetime':
                     $this->{$colName} = $this->Text();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->maxlength = '20';                 
                     break;
                     
                 case 'Ipaddress':
                     $this->{$colName} = $this->Text();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->size = '18';
                     $this->{$colName}->maxlength = $col->getParam('maxlength');
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                     
                 case 'Url':
                     $this->{$colName} = $this->Text();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->size = '30';
                     $this->{$colName}->maxlength = $col->getParam('maxlength');
                     $this->{$colName}->validators->Url(translate('O campo <b>{{campo}}</b> n&atilde;o &eacute; um URL v&aacute;lido.', $this->{$colName}->label));
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                 
                 case 'Boolean':
                     $this->{$colName} = $this->Checkbox();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     if ($col->getParam('default')) {
                         $this->{$colName}->value = $col->getParam('default');
                     }                     
                     break;
                     
                 case 'Email':
                     $this->{$colName} = $this->Text();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->size = '30';
                     $this->{$colName}->maxlength = $col->getParam('maxlength');
                     $this->{$colName}->validators->Email(translate('O campo <b>{{campo}}</b> n&atilde;o &eacute; um email v&aacute;lido.', $this->{$colName}->label));                     
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                     
                 case 'Image':
                     $this->{$colName} = $this->File();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     if (!$col->getParam('target')) {
                         throw new Goweb_Exception("&Eacute; necess&aacute;rio definir o par&acirc;metro 'target' com o nome do direct&oacute;rio para efectuar o upload");
                     }
                     $this->{$colName}->validators->ImageType(translate('O ficheiro carregado n&atilde;o &eacute; do tipo imagem'));
                                      
                     $this->{$colName}->validators->ImageDimensions(translate('As dimen&ccedil;&otilde;es m&aacute;ximas da imagem &eacute; de ') .
                     $col->getParam('max_width') . 'x' . $col->getParam('max_height') . ' (pixels)',
                                                                    array('max_width'  => $col->getParam('max_width'),
                                                                          'max_height' => $col->getParam('max_height')));
                                                                    
                     if ($col->getParam('max_size')) {
                         $this->{$colName}->validators->FileSize(translate('O tamanho m&aacute;ximo do ficheiro &eacute; de') . ' ' . ceil($col->getParam('max_size') / 1024) . ' ' . 'Kb',
                                                                 array('max_size' => $col->getParam('max_size')));
                         
                     }

                     $del = $colName . '_del';
                     if ($col->getParam('notnull') &&
                         $this->{$colName}->value == null &&
                         $this->_request->{$del} == '1' &&
                         !$this->{$colName}->validatorExists('Goweb_Validate_Required')) {
                             $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                         }
                     break;
                     
                 case 'File':                     
                     $this->{$colName} = $this->File();
                     $this->{$colName}->label = $label;
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     if (!$col->getParam('target')) {
                         throw new Goweb_Exception("&Eacute; necess&aacute;rio definir o par&acirc;metro 'target' com o nome do direct&oacute;rio para efectuar o upload");
                     }
                     if ($col->getParam('max_size')) {
                         $this->{$colName}->validators->FileSize(translate('O tamanho m&aacute;ximo do ficheiro &eacute; de') . ' ' . ceil($col->getParam('max_size') / 1024) . ' ' . 'Kb',
                                                                 array('max_size' => $col->getParam('max_size')));
                     }
                     
                     if ($col->getParam('types')) {
                         $this->{$colName}->validators->FileType(translate('Apenas s&atilde;o v&aacute;lidos ficheiros do tipo "{{tipos}}"', is_array($col->getParam('types')) ? implode(', ', $col->getParam('types')) : $col->getParam('types')),
                                                                 $col->getParam('types'));
                     
                     	
                     }
                     
                     $del = $colName . '_del';
                     if ($col->getParam('notnull') &&
                         $this->{$colName}->value == null &&
                         $this->_request->{$del} == '1' &&
                         !$this->{$colName}->validatorExists('Goweb_Validate_Required')) {
                             $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                     }
                     break;
                 
                 case 'Select': // atencao: o Select deve ser utilizado com model
                     
                     $this->{$colName} = $this->Select();
                     $this->{$colName}->label = $label;
                     
                     $selectModelName = $col->getParam('model');
                     $selectModel = Goweb::getModelInstance($selectModelName, $this->_model->getAdapter(), false, true);
                     
                     if (!$model->isLoaded() && $parent == $colName && $parent_id) {
                         $this->{$colName}->value = $parent_id;
                     } elseif ($model->isLoaded()) {
                         $this->{$colName}->value = $model->{$colName};
                     }
                     
                     $options = array();
                     $options[$col->getParam('default')] = html_entity_decode(translate('Escolha uma op&ccedil;&atilde;o'), ENT_NOQUOTES, CHARSET);
                     
                     if ($col->getParam('order')) {
                         $selectModel->order($col->getParam('order'));
                     }
                     
                     $rowset = $selectModel->fetchAll();                 
                     if ($rowset) {
                         $key = $selectModel->getPrimary();
                         $label = $selectModel->getToString();
                         if (!strlen($label)) {
                             $label = $key;
                         }
                         foreach ($rowset as $row) {
                             $options[$row->{$key}] = $row->{$label};
                         }
                     } 
                     
                     $this->{$colName}->options = $options;
                     
                     $this->{$colName}->multiple = $col->getParam('multiple');
                     $this->{$colName}->size = $col->getParam('size');
                     
                     $this->{$colName}->error_class = 'error';
                     $this->{$colName}->focus_class = 'focus';
                     break;
                     
                 case 'Filepath':                              
                 case 'Time':            
                 case 'Auto':
                 case 'Blob':                          
                 default:
                     break;
                }
                
                if ($col->getParam('unique') && ($this->_model->{$colName} != $this->_request->{$colName})) {
                    $this->{$colName}->validators->Unique(translate('O <b>{{campo}}</b> j&aacute; existe no sistema</b>', $label),
                                                          array('model' => $this->_model,
                                                                'col'   => $colName));
                }               
                
                if ($col->getType() != 'File' &&
                    $col->getType() != 'Image' &&
                    $col->getType() != 'SelfKey' &&
                    $col->getParam('notnull') &&
                    !$this->{$colName}->validatorExists('Goweb_Validate_Required')) {
                        $this->{$colName}->validators->Required(translate('O campo <b>{{campo}}</b> &eacute; de preenchimento obrigat&oacute;rio.', $this->{$colName}->label));
                    }
                
                if ($colName != $this->_model->getPrimary()) {
                    $this->{$colName}->help = $col->getParam('help');
                    if ($this->_model->isLoaded()) {
                        if (strpos($this->_model->{$colName}, 'a:') === 0 && ($col->getType() == 'ForeignKeyMultiple' || $col->getType() == 'Char')) {
                            $this->{$colName}->value = unserialize($this->_model->{$colName});
                        } else {
                            if ($col->getType() != 'Date' || $this->_model->{$colName} != '0000-00-00')
                            $this->{$colName}->value = $this->_model->{$colName};
                        }
                    } elseif (!$this->{$colName}->value && $col->getParam('default')) {
                        $this->{$colName}->value = $col->getParam('default');                    
                    }
                }
                
                //add one to many
                if ($col->getParam('on_insert')){
                    $this->{$colName}->setAttrib('disable', true);
                    if ($this->{$colName}->validatorExists('Goweb_Validate_Required')){
                        $this->{$colName}->removeValidator('Goweb_Validate_Required');
                        $this->{$colName}->setRequired(false);
                    }
                    
                }

                if ($col->getParam('readonly') && $this->_model->isLoaded()){
                    if ($this->{$colName}->validatorExists('Goweb_Validate_Required')){
                        $this->{$colName}->removeValidator('Goweb_Validate_Required');
                        $this->{$colName}->setRequired(false);
                    }
                    $this->{$colName}->setAttrib('disable', true);
                    $this->{$colName}->value = $this->_model->{$colName};
                }
            }
        }
        
        $this->submit = $this->Submit();
        $this->submit->value = translate('Gravar');
        $this->submit->class = 'form_submit';
        $this->submit_and_new = $this->Submit();
        $this->submit_and_new->value = translate('Gravar e adicionar novo');
        $this->submit_and_new->class = 'form_submit_and_new';
        $this->submit_and_continue = $this->Submit();
        $this->submit_and_continue->value = translate('Gravar e continuar a editar');
        $this->submit_and_continue->class = 'form_submit_and_continue';
    }
    

    /**
     * Criar arvore
     *
     * @param Goweb_Db_Model $model
     * @param array $nodesParams
     * @return Goweb_Js_Tree
     */
    protected function _getModelTree($model = 'Cms_Model_Pagina', $nodesParams = array('id'=> 'id', 'pid' => 'pai_id', 'name' => 'titulo'), $colName = null) {
        
        if (is_string($model)) $model = Goweb::getModelInstance($model, 'db', false);

        // valida se foram passados os campos necesserio para o node
        if (!array_key_exists('id', $nodesParams)) {
            throw new Goweb_Exception("O campo  'id' &eacute; necess&aacute;rio nos par&aacute;metros dos nodes.");
        }
        if (!array_key_exists('pid', $nodesParams)) {
            throw new Goweb_Exception("O campo  'pid' &eacute; necess&aacute;rio nos par&aacute;metros dos nodes.");
        }
        if (!array_key_exists('name', $nodesParams)) {
            throw new Goweb_Exception("O campo  'name' &eacute; necess&aacute;rio nos par&aacute;metros dos nodes.");
        }

        $idCol = $nodesParams['id'];
        $pidCol = $nodesParams['pid'];
        $nameCol = $nodesParams['name'];
        $model->loadForeigns(false);
        Goweb::loadClass('Goweb_Tree');
        $tree = new Goweb_Tree($idCol, $pidCol);
        if ($model->colExists('ordem')) $model->order('ordem'); // ordena as paginas pelo campo ordem da bd
        
        $cols = array($idCol, $pidCol, $nameCol, 'redireccionar');
        foreach ($cols as $key => $col){
            if (!$model->colExists($col)) unset($cols[$key]);
        }
        $rowset = $model->fetchAll($cols);
        $link = '';
        if (!is_null($colName)){
            $link = "$(\"" . $colName . "\").value=\"{{id}}\"; Modalbox.hide(); return false;";
        }

        if ($rowset) {
            foreach ($rowset as $row) {
                $titulo = $row->{$nameCol};
                if (!is_null($colName)){
                    $titulo = "<a href='' onclick='" . $link . "'>" . $titulo . "</a>";
                    $titulo = str_replace('{{id}}', $row->{$idCol}, $titulo);
                }
                $node = array($idCol => $row->{$idCol},
                $pidCol => $row->{$pidCol},
                $nameCol => $titulo);

                // adiciona o node
                $tree->addElement($node);
            }
        }

        // retorna o Goweb_Js_Tree
        return $tree;
    }

    /**
     * Formata uma string para se mostrada como label.
     *
     * Substitui palavras separadas por "-", "_", ou "." por maiusculas e
     * remove todos caracteres que n&atilde;o sejam alfanemericos.
     * 
     * @param   string
     * @return  string
     */
    protected function _formatNameForLabel($unformatted) {
        $unformatted = str_replace(array('-', '_', '.'), ' ', strtolower($unformatted));
        $unformatted = preg_replace('[^a-z0-9 ]', '', $unformatted);
        return ucwords($unformatted);
    }
    
    protected function _elementsOrder($orderArray) {
        $ordered = array();
        foreach($orderArray as $key) {
            if(array_key_exists($key, $this->_elements)) {
                $ordered[$key] = $this->_elements[$key];
                unset($this->_elements[$key]);
            }
        }
        $this->_elements = $ordered + $this->_elements;
    }
}