<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class configurator_callbacks {

    public function input($key, $value) {
        $template = '<input type="text" id="conf_' . $key . '" name="' . $key . '" value="' . $value . '">';

        return $template;
    }

    public function textarea($key, $value) {
        $template = '<textarea id="conf_' . $key . '" name="' . $key . '" class="input-xxlarge" rows="10">' . $value . '</textarea>';

        return $template;
    }

    public function radio($key, $value) {
        $template = '
            <div>
                <div class="btn-group" data-toggle="buttons-radio">
                    <button type="button" class="configurator_radio btn ' . (empty($value) ? '' : 'active') . '" value="1">{ln_radio_active}</button>
                    <button type="button" class="configurator_radio btn ' . (!empty($value) ? '' : 'active') . '" value="0">{ln_radio_no_active}</button>
                </div>
                <input type="hidden" name="' . $key . '" value="' . intval($value) . '" />
            </div>';

        $js = '$(function(){
                    $(\'.configurator_radio\').click(function(){
                        var el = $(this);
                        el.parent().parent().find(\'input[type=hidden]\').val(el.val());
                        el.parent().find(\'.configurator_radio\').removeClass(\'active\');
                        el.addClass(\'active\');
                    });
                });';
        $CI = & get_instance();
        $CI->js_css->add_js_string($js);

        return $template;
    }

}

/**
 * Description of configurator
 *
 * @author Igor Ratsun
 */
class configurator {

    public $templates = array(
        'control_group' => '<div class="control-group"><label class="control-label" for="conf_{key}">{name}</label><div class="controls">{item}</div></div>',
        'button' => '<div class="form-actions"><button type="submit" class="btn btn-primary" id="btn_save">{btn_save}</button></div>',
        'message' => '<div class="alert alert-success" style="display:none" id="msg_ok">{msg_ok}</div>'
    );
    public $language = array();
    private $CI = null;
    private $get_config = array();
    protected $acl_resource_name = null;
    protected $_params = array();
    protected $display_as = array();

    /**
     * 
     * @param string $resource ACL resource
     */
    public function __construct($resource = '') {
        $this->CI = & get_instance();
        $this->_default_callback = new configurator_callbacks();
        $this->language = $this->CI->lang->load('ciext/configurator', '', TRUE);
        if (!empty($resource)) {
            $this->set_resource($resource);
        }
    }

    /**
     * Get resource configuration
     * @return array
     */
    public function get_config() {
        if (empty($this->acl_resource_name)) {
            return array();
        }

        if (empty($this->get_config[$this->acl_resource_name])) {
            $sql = $this->CI->db->
                            select('data')->
                            join('acl_resource', 'acl_resource.id_acl_resource = configuration.id_acl_resource')->
                            where('acl_resource.acl_resource_name', $this->acl_resource_name)->
                            get('configuration')->row_array();
            $this->get_config[$this->acl_resource_name] = (isset($sql['data'])) ? unserialize($sql['data']) : array();
        }

        return $this->get_config[$this->acl_resource_name];
    }
    
    /**
     * Get config value by key
     * @param string $key
     * @return mixed string|FALSE
     */
    public function item($key = '')
    {
        $data = $this->get_config();
        
        // Aliases
        if ($key == 'email_from') {
            $cnf = new configurator('emailmng');
            return $cnf->item('sender_email');
        }
        
        return !empty($data[$key]) ? $data[$key] : FALSE;
    }

    /**
     * Set resource configuration
     * @param array $data
     * @return boolean
     */
    public function set_config($data = array()) {
        if (empty($this->acl_resource_name)) {
            return FALSE;
        }

        $resource = $this->CI->db->
                        select('id_acl_resource')->
                        where('acl_resource_name', $this->acl_resource_name)->
                        get('acl_resource')->row_array();

        if (empty($resource['id_acl_resource'])) {
            return FALSE;
        }

        $config = $this->get_config();

        if (!empty($config)) {
            $this->CI->db->
                    where('id_acl_resource', $resource['id_acl_resource'])->
                    update('configuration', array('data' => serialize($data)));
        } else {
            $this->CI->db->
                    insert('configuration', array(
                        'id_acl_resource' => $resource['id_acl_resource'],
                        'data' => serialize($data)
            ));
        }

        // Update data
        $this->get_config = $data;

        return TRUE;
    }

    /**
     * Set acl resource
     * @param string $acl_resource_name
     * @return \configurator
     */
    public function set_resource($acl_resource_name = null) {
        $this->acl_resource_name = $acl_resource_name;
        
        return $this;
    }

    /**
     * Set key alias
     * @param string $key
     * @param string $value
     * @return \configurator
     */
    public function display_as($key, $value) {
        $this->display_as[url_title($key)] = $value;

        return $this;
    }

    /**
     * Set users callback function for key
     * @param string $key
     * @param array/string $callback
     * @return \configurator
     */
    public function add_item($key, $callback = NULL) {
        if (empty($callback)) {
            $callback = array(new configurator_callbacks(), 'input');
        }
        $this->_params[url_title($key)] = $callback;

        return $this;
    }

    public function __call($name, $args) {
        if (empty($args[0])) {
            throw new Exception('Empty key');
        }

        $key = $args[0];
        $default = new configurator_callbacks();
        $method = str_replace('add_', '', $name);

        if (method_exists($default, $method)) {
            $this->add_item($key, array($default, $method));
        } else {
            throw new Exception('Method ' . $method . ' not found');
        }

        return $this;
    }

    protected function _get_params() {
        $res = '';
        $data = $this->get_config();
        foreach ($this->_params as $k => $v) {
            $name = isset($this->display_as[$k]) ? $this->display_as[$k] : $k;
            $value = !empty($data[$k]) ? $data[$k] : '';

            $array = array('key' => $k, 'name' => $name, 'value' => $value);

            $template = (!empty($v)) ? call_user_func($v, $k, $value) : '';

            $res .= $this->CI->parser->parse_string(str_replace('{item}', $template, $this->templates['control_group']), $array, TRUE);
        }

        return $res;
    }

    /**
     * Get configurator interface
     * @return string
     */
    public function render() {
        // Ajax save data
        if (!empty($_POST)) {
            $ins_data = array();
            foreach ($_POST as $k => $v) {
                if (!empty($this->_params[$k])) {
                    $ins_data[$k] = $v;
                }
            }

            die($this->set_config(array_merge($this->get_config(), $ins_data)));
        }

        $this->CI->ciext->load_bootstrap();
        $js = '$(document).ready(function() {
                $(\'#btn_save\').click(function(){
                    var link = $(\'#change_form\').attr(\'action\');
                    $.post(link, $(\'#change_form\').serialize(), function(data) {
                        var obj = jQuery.parseJSON(data);
                        $(\'#change_form .error\').removeClass(\'error\');
                        $(\'#msg_ok\').hide();
                        if (typeof obj.errors != \'undefined\') {
                            jQuery.each(obj.errors, function(k, v) {
                                $(\'#\' + v).parents(\'div.control-group\').addClass(\'error\');
                            });
                        } else {
                            $(\'#msg_ok\').show(\'normal\');
                        }
                    });

                    return false;
                });
            })';
        $this->CI->js_css->add_js_string($js);
        $this->CI->load->helper('form');

        $res = $this->_get_params();

        if (!empty($res)) {
            $template = form_open('', 'id="change_form" class="form-horizontal"') .
                    $this->templates['message'] .
                    $res .
                    $this->templates['button'] .
                    form_close();
            
            // Add languages
            return $this->CI->parser->parse_string($template, $this->language, TRUE);
        }


        return $res;
    }

}

