<?php

/**
 * JTreeTable class file.
 *
 * @author jerry2801 <jerry2801@gmail.com>
 *
 * @version alpha 4 (2010-10-20 18:48)
 * @version alpha 3 (2010-8-12 14:05)
 * @version alpha 2 (2010-6-4 13:28)
 * @version alpha 1 (2010-4-30 15:57)
 * @requires treeTable v2.3.0 (http://ludo.cubicphuse.nl/jquery-plugins/treeTable/doc/index.html, http://plugins.jquery.com/project/treeTable)
 *
 * A typical usage of JTreeTable is as follows:
 * <pre>
 * $this->widget('ext.treetable.JTreeTable',array(
 *     'id'=>'treeTable',
 *     'primaryColumn'=>'id',
 *     'parentColumn'=>'parent_id',
 *     'columns'=>array(
 *         'id'=>array(
 *             'label'=>'Id',
 *             'headerHtmlOptions'=>array('width'=>80),
 *             'htmlOptions'=>array('align'=>'center'),
 *         ),
 *         'name'=>'Name',
 *     ),
 *     'items'=>array(
 *         array('id'=>1,'parent_id'=>0,'name'=>'test 1'),
 *         array('id'=>2,'parent_id'=>1,'name'=>'test 1\'s children 1'),
 *     ),
 *     'options'=>array(
 *         'initialState'=>'expanded',
 *     ),
 * ));
 * </pre>
 */

class JTreeTable extends CWidget
{
    public $id;
    public $columns;
    public $items;
    public $primaryColumn;
    public $parentColumn;
    public $options=array();
    public $model;
    public $sortField;
    public $fields=array();
    public $ajaxRequest = false;
    public $getChildrenUrl;
    public $updateItemUrl;
    public $expanded = false;

    public function init()
    {
        if($this->ajaxRequest){
            $parentId = $_REQUEST['id'];            
            
            foreach($this->findChilderen($this->model) as $child){
                $this->renderChildren($child, false, $parentId);
            }
            
        }
        else{
          $this->getRootItems();  
        }
    }

    public function run()
    {
		$options=CJavaScript::encode($this->options);

        $path=dirname(__FILE__).DIRECTORY_SEPARATOR.'source';
        $baseUrl=Yii::app()->getAssetManager()->publish($path);

        $id=$this->id;

        //$js='$("#'.$id.'").treetable('.$options.');';

		$cs = Yii::app()->getClientScript();

        /*$juiBasePath=Yii::getPathOfAlias('zii.vendors.jui');
        $juiBaseUrl=Yii::app()->getAssetManager()->publish($juiBasePath);
        $cs->registerCssFile($juiBaseUrl.'/css/base/jquery-ui.css');
        $cs->registerScriptFile($juiBaseUrl.'/js/jquery-ui.min.js');*/

        $cs->registerCssFile($baseUrl.'/stylesheets/jquery.treeTable.css');
        $cs->registerScriptFile($baseUrl.'/javascripts/jquery.treetable.js');
        $cs->registerScriptFile($baseUrl.'/javascripts/jquery-ui-1.10.1.custom.min.js');
        

		//$cs->registerScript(__CLASS__.'#'.$id,$js);
    }
    
    protected function getRootItems(){
        
        $this->registerScripts();
        $this->createTableHeader();
        $this->createTableBody();
        $this->createTableFooter();

    }
    
    protected function getModel(){
        //dump($this->model);die();
        if(is_string($this->model)){
            $modelName = $this->model;            
            $class = new $modelName();             
            $this->model = $class::model();            
        }
        return $this->model;
    }
    
    protected function createTableHeader(){
        echo '<table id="'.$this->id.'" width="100%" class="plTable items table table-striped table-bordered table-condensed">';    
        echo '<thead><tr>';                
        
        
        
        foreach($this->columns as $key=>$props)
        {
            $attributeLabels = $this->getModel()->attributeLabels();
            //dump($attributeLabels);
            $attribute = is_array($props) ? $key : $props;
            

            //$label = is_array($props) ? $props['label'] : $attributeLabels[$attribute];
            
            $htmlOptions = is_array($props) && isset($props['headerHtmlOptions'])?$props['headerHtmlOptions']:array();
            
            //$htmlOptions['data-translation-id'] = "USERGROUPS_MODEL_NAME";
            //dump($props);
            $label = isset($props['header']) ? $props['header'] : $attributeLabels[$key];
            //$translatedLabel = isset($attributeLabels[$label]) ? $attributeLabels[$label] : $label;
            echo CHtml::openTag('th',$htmlOptions).$label.CHtml::closeTag('th');
        }
        
        echo '</tr></thead><tbody>';
    }
    
    protected function registerScripts(){
        $expandetState = $this->expanded ? "expanded" : "collapsed";
                
        $script = 
        'var table_'.$this->id.' = $("#'.$this->id.'");
        var rootLoaded = false;
        
        $("#'.$this->id.'").treetable({
          initialState: "'. $expandetState .'",
          expandable: true,
          /*onNodeCollapse: function() {
            var node = this;
            table_'.$this->id.'.treetable("unloadBranch", node);
          },
          onNodeExpand: function() {
            var node = this;
    
            // Render loader/spinner while loading
            $.ajax({
              async: false, // Must be false, otherwise loadBranch happens after showChildren?
              url: "'.$this->getChildrenUrl.'",
              data: { id: node.id }
            }).done(function(html) {
              var rows = $(html).filter("tr");
    
              rows.find(".group").parents("tr").each(function() {
                droppableSetup.apply(this);
                draggableSetup.apply($(this).find("span").first());
              })
    
              table_'.$this->id.'.treetable("loadBranch", node, rows);
            });
          }*/
        });
        
        
        function droppableSetup() {
            
              $(this).droppable({
                accept: ".file, .directory, .group",
                drop: function(e, ui) {
                  var droppedEl, node;
                  
                  droppedEl = ui.draggable.parents("tr");
                  node = table_'.$this->id.'.treetable("node", droppedEl.data("ttId"));
        
                  table_'.$this->id.'.treetable("move", node.id, $(this).data("ttId"));
                 
                  // Update server-side tree
                  $.ajax({
                    data: { parentId: node.parentId, id: node.id, '.Yii::app()->request->csrfTokenName . ': "' . Yii::app()->request->csrfToken . '"'.'},
                    type: "POST",
                    url: "'.$this->updateItemUrl.'",
                  });
                },
                hoverClass: "accept",
                over: function(e, ui) {
                  var droppedEl = ui.draggable.parents("tr");
                  if(this != droppedEl[0] && !$(this).is(".expanded")) {
                    table_'.$this->id.'.treetable("expandNode", $(this).data("ttId"));
                  }
                }
              });
            }
            
        function draggableSetup() {
            if(!rootLoaded){
                console.log("xxx");
                rootLoaded = true;
                return;
            }
            return;

            
            $(this).draggable({
              helper: "clone",
              opacity: .75,
              refreshPositions: true,
              revert: "invalid",
              revertDuration: 300,
              scroll: true,
            });
        }
        
        
        
        
        
        
        // Highlight selected row
        $("#'.$this->id.' tbody tr").mousedown(function() {
          $("tr.selected").removeClass("selected");
          $(this).addClass("selected");
        });
        
        // Drag & Drop Example Code
        
        // remove first root element
        $("#'.$this->id.' .group").slice(1).draggable({
          helper: "clone",
          opacity: .75,
          refreshPositions: true,
          revert: "invalid",
          revertDuration: 300,
          scroll: true
        });
        
        
        /*
var rows = $(html).filter("tr");
    
              rows.find(".group").parents("tr").each(function() {
                droppableSetup.apply(this);
                draggableSetup.apply($(this).find("span").first());
              })
*/


        $("#'.$this->id.' .group").each(function() {
          $(this).parents("tr").each(function() {
                droppableSetup.apply(this);
                draggableSetup.apply($(this).find("span").first());
              })
        });
        
        /*
        $("#'.$this->id.' .group").each(function() {
          $(this).parents("tr").droppable({
            accept: ".file, .folder, .group",
            drop: function(e, ui) {
              var droppedEl = ui.draggable.parents("tr");
              $("#'.$this->id.'").treetable("move", droppedEl.data("ttId"), $(this).data("ttId"));
            },
            hoverClass: "accept",
            over: function(e, ui) {
              var droppedEl = ui.draggable.parents("tr");
              if(this != droppedEl[0] && !$(this).is(".expanded")) {
                $("#'.$this->id.'").treetable("expandNode", $(this).data("ttId"));
              }
            }
          });
        });
        */
        ';
        
        Yii::app()->clientScript->registerScript('logoFix',$script);
    }
    
    protected function createTableBody(){
        
        $rootModel = $this->getModel();
        
        $this->renderModel($rootModel);
        

        foreach ($this->findChilderen($rootModel) AS $k => $model){
            //$this->renderChildren($model);
            $this->renderChildren($model, true, str_replace("-", "_", $rootModel->id));
        } 
       
    }
    
    protected function createTableFooter(){
        echo '</tbody>';
        echo '</table>';
    }
    

    
    protected function hasChildren($model){
        return count($this->findChilderen($model)) != 0;
    }
    
    
    
    protected function renderCustomButtons($template, $buttons, $data)
    {    
        $result = '';
        ob_start();
        foreach($buttons as $name => $button){
            $this->renderTemplateButton($button, $data);
            $result .= ob_get_contents();
            ob_clean();
        }
        ob_end_clean();
        return $result;
    }
    
    
    
    protected function renderTemplateButton($button, $data)
    {
        $row = '';
        
		if (isset($button['visible']) && !$this->evaluateExpression($button['visible'], array('row'=>$row, 'data'=>$data)))
			return;

		$label = isset($button['label']) ? $button['label'] : $id;
		$url = isset($button['url']) ? $this->evaluateExpression($button['url'], array('data'=>$data, 'row'=>$row)) : '#';
		$options = isset($button['options']) ? $button['options'] : array();

		if (!isset($options['title']))
			$options['title'] = $label;

		if (!isset($options['rel']))
			$options['rel'] = 'tooltip';
			
        $confirm = isset($button['confirm']) ? 'return confirm("'.$button['confirm'].'");' : '';

        if(isset($button['ajax'])){
    		echo CHtml::ajaxLink(
              $label,
              $url,
              array( // ajaxOptions
                'confirm' => 'conf',
                'type' => isset($button['type']) ? $button['type'] : 'GET',
                'beforeSend' => "function(request){
                    ".$confirm.";
                    // Set up any pre-sending stuff like initializing progress indicators
                }",
                'success' => $button['success'],
                'data' => array(Yii::app()->request->csrfTokenName => Yii::app()->request->csrfToken)
              ),
              $options
            );
            return;   
        }

		
		if (isset($button['icon']))
		{
			if (strpos($button['icon'], 'icon') === false)
				$button['icon'] = 'icon-'.implode(' icon-', explode(' ', $button['icon']));

			echo CHtml::link('<i class="'.$button['icon'].'"></i>', $url, $options);
		}
		else if (isset($button['imageUrl']) && is_string($button['imageUrl']))
			echo CHtml::link(CHtml::image($button['imageUrl'], $label), $url, $options);
		else
			echo CHtml::link($label, $url, $options);
    }
    
    protected function renderModel($model, $parentDataId=null){
        $dataId = $parentDataId == null ? str_replace("-", "_", $model->id) : $parentDataId . "-" . str_replace("-", "_", $model->id);
        $parentDataIdAttr = $parentDataId != null ? ' data-tt-parent-id="' . $parentDataId . '"' : '';
        
        $htmlOptions = array();
        $htmlOptions['data-tt-branch'] = $this->hasChildren($model) ? 'true' : 'false';
        $htmlOptions['data-tt-id'] = $dataId;
        $htmlOptions['data-tt-parent-id'] = $parentDataId != null ? $parentDataId : null;
        
        echo CHtml::openTag('tr', $htmlOptions);
        
        foreach($this->columns as $key=>$props){
            $attribute = is_array($props) ? $key : $props;
            
            if (isset($props['visible']) && !$this->evaluateExpression($props['visible'], array('row'=>null, 'data'=>$model))){
                echo '<td></td>';
                continue;
            }
            
                        
            if(isset($props['value'])){
                echo '<td><span class="group">'.$this->evaluateExpression($props['value'], array('row'=>null, 'data'=>$model)).'</span></td>';
            }
            else if(in_array($attribute, $model->myAttributes())){
                echo '<td><span class="group">'.CHtml::encode($model->$attribute)."</span></td>";
            }
            else if(isset($props['template'])){
                echo '<td class="buttonColumnIcons">' . $this->renderCustomButtons($props['template'], $props['buttons'], $model) . '</td>';
            }
            else{
                echo '<td>'.CHtml::encode($model->$attribute).'</td>';
            }
        }     
        
        echo "</tr>";
        return $dataId;
    } 
    
    protected function renderChildren($model, $recursive = false, $parentDataId=null){
        
        $dataId = $this->renderModel($model, $parentDataId);

        if($recursive){
            foreach($this->findChilderen($model) as $child){
                $this->renderChildren($child, $recursive, $dataId);
            }
        }
    }
    
    protected function findChilderen($model){
        return $model->find(array($this->parentColumn => $model->id), $this->sortField);
    }
  
    
    static function renderChildModels($model){
        self::renderChildren($model, false, $parentDataId=null);
    }
    
}