<?php

/**
 * Wrapper for ivaynberg jQuery select2 (https://github.com/ivaynberg/select2)
 *
 * @author Anggiajuang Patria <anggiaj@gmail.com>
 * @link http://git.io/Mg_a-w
 * @license http://www.opensource.org/licenses/apache2.0.php
 */
class ESelect2 extends CInputWidget
{

    /**
     * @var array select2 options
     */
    public $options = array('language' => 'pt-BR');

    public $defaultsRegister = array(
        'allowClear' => false,
        'placeholder' => 'Selecione',
        'minimumInputLength' => 3
        );
    public $defaultsSearch = array(
        'allowClear' => false,
        'placeholder' => 'Todos',
        'minimumInputLength' => 3
        );

    public $searchForm = false;

    public $relatedModel;
    public $relatedValue = false;
    public $relatedValue2 = false;

    /**
     * @var array CHtml::dropDownList $data param
     */
    public $data = array();

    /**
     * @var string html element selector
     */
    public $selector;

    /**
     * @var array config fotr ajax remote load
     */
    public $ajaxConf = array();

    /**
     * @var array javascript event handlers
     */
    public $events = array();

    protected $defaultOptions = array();

    public function init()
    {
        $this->defaultOptions = array(
            'formatNoMatches'           => 'js:function() { return "Nenhum resultado"; }',
            'formatInputTooShort'       => 'js:function(input,min) { return "Digite mais "+(min-input.length)+" caracteres"; }',
			'formatInputTooLong'        => 'js:function(input,max) { return "Digite "+(input.length-max)+" caracteres a menos"; }',
            'formatSelectionTooBig'     => 'js:function(limit) { return "Você só pode selecionar "+limit+" item"; }',
            'formatLoadMore'            => 'js:function(pageNumber) { return "Carregando.."; }',
            'formatSearching'           => 'js:function() { return "Procurando.."; }',
        );
    }

    public function run()
    {
        if ($this->selector == null) {
            list($this->name, $this->id) = $this->resolveNameId();
            $this->selector = '#' . $this->id;

            if (isset($this->htmlOptions['placeholder']))
                $this->options['placeholder'] = $this->htmlOptions['placeholder'];

            if(empty($this->value)){
                $this->value = $this->model->{$this->attribute};
            }
            if(empty($this->data) && !empty($this->value)) {

                $data = array();
                if (isset($this->options['placeholder'])) {
                    $data[''] = '';
                }
                $this->data = $data + $this->data;

                $relatedModel = new $this->relatedModel;
                $relatedValue = ($this->relatedValue) ? $this->relatedValue : $relatedModel->representingColumn();
                
                if (!isset($this->htmlOptions['multiple'])) {
                    $relatedData = $relatedModel->findByPk($this->value);
                    if($relatedData){
                        $this->data[$this->value] = (string) $relatedData->{$relatedValue} . ($this->relatedValue2 && !empty($relatedData->{$this->relatedValue2}) ? ' (' . $relatedData->{$this->relatedValue2} . ')' : '');
                    }
                } else {
                    if (!is_array($this->value)) {
                        $this->value = explode(',',$this->value);
                    }
                    foreach($this->value as $value) {
                        $relatedData = $relatedModel->findByPk($value);
                        if($relatedData){
                            $this->data[$value] = (string) $relatedData->{$relatedValue} . ($this->relatedValue2 && !empty($relatedData->{$this->relatedValue2}) ? ' (' . $relatedData->{$this->relatedValue2} . ')' : '');
                        }
                    }
                }
            }

            if (!$this->hasModel()) {
                $this->htmlOptions['id'] = $this->id;
            }
            if (!empty($this->model->getError($this->attribute))) {
                if(!isset($this->htmlOptions['class'])) {
                    $this->htmlOptions['class'] = "";
                }
                $this->htmlOptions['class'] .= ' error'; 
            }
            echo CHtml::dropDownList($this->name, $this->value, $this->data, $this->htmlOptions);
        }

        if(!empty($this->ajaxConf)) {
            if(!isset($this->ajaxConf['params'])) {
                $this->ajaxConf['params'] = array();
            }
            $this->ajaxConf['params'][] = 'term: params.term';
            $this->ajaxConf['params'][] = 'json: true';

            $this->options['ajax'] = array(
                'type' => 'get',
                'url' => $this->ajaxConf['url'],
                'dataType' => 'json',
                'contentType' => 'application/json',
                'delay' => 100,
                'data' => 'js:function (params) { return { '.implode(',', $this->ajaxConf['params']).' }; }',
                'processResults' => 'js:function (data, params) { return { results: data }; }',
            );
        }
        $bu = Yii::app()->assetManager->publish(dirname(__FILE__) . '/assets/');
        $cs = Yii::app()->clientScript;

        if (YII_DEBUG) {
            $cs->registerScriptFile($bu . '/js/select2.js', CClientScript::POS_BEGIN);
            $cs->registerCssFile($bu . '/css/select2.css');
        } else {
            $cs->registerScriptFile($bu . '/js/select2.min.js', CClientScript::POS_BEGIN);
            $cs->registerCssFile($bu . '/css/select2.min.css');
        }
        $cs->registerScriptFile($bu . '/js/i18n/pt-BR.js', CClientScript::POS_BEGIN);
        $defaults = ($this->searchForm) ? $this->defaultsSearch : $this->defaultsRegister;
        foreach($defaults as $option => $value) {
            if(!isset($this->options[$option])) {
                $this->options[$option] = $value;
            }
        }
        $options = CJavaScript::encode(CMap::mergeArray($this->defaultOptions, $this->options));

        $script = "$('{$this->selector}').select2({$options})";
        foreach ($this->events as $event => $handler) {
            $script .= ".on('{$event}', " . CJavaScript::encode($handler) . ")";
        }
        $script .= ';';
        $cs->registerScript(__CLASS__ . '#' . $this->id, $script);
    }

}
