<?php

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

/**
 * Description of Acl_model
 *
 * @author Igor Ratsun
 */
class Acl_model extends CI_Model {

    /**
     * Get roles
     * @return array 
     */
    public function get_roles() {
        return $this->db->
                        select('id_acl_role, acl_role_name')->
                        where('active', '1')->
                        order_by('acl_role_name', 'ASC')->
                        get('acl_role')->result_array();
    }

    /**
     * Get acl resources
     * @return array 
     */
    public function get_acl_resources() {
        if (empty($this->_get_acl_resources)) {
            $q = $this->db->
                            select('id_acl_resource, acl_resource_name, acl_resource_alias')->
                            where('active', '1')->
                            get('acl_resource')->result_array();
            if (empty($q)) {

                return array();
            }

            foreach ($q as $v) {
                $this->_get_acl_resources[$v['id_acl_resource']] = $v;
            }
        }

        return $this->_get_acl_resources;
    }

    protected $_get_acl_resources = array();

    /**
     * Get actions
     * @param int $id_acl_role
     * @param int $id_resource
     * @return array 
     */
    public function get_actions($id_acl_role, $id_resource) {
        if (empty($this->_get_actions[$id_acl_role][$id_resource])) {
            $q = $this->db->
                            select('acl_action.id_acl_action, acl_action.acl_action_name, acl_action.acl_action_alias, acl_rule.id_acl_rule')->
                            join('acl_rule', 'acl_rule.id_acl_action = acl_action.id_acl_action AND acl_rule.id_acl_role = ' . $id_acl_role . ' AND acl_rule.id_acl_resource = ' . $id_resource, 'left')->
                            where('acl_action.id_acl_resource', $id_resource)->
                            order_by('acl_action.acl_action_alias', 'ASC')->
                            get('acl_action')->result_array();
            if (empty($q)) {

                return array();
            }

            foreach ($q as $v) {
                $this->_get_actions[$id_acl_role][$id_resource][$v['id_acl_action']] = $v;
            }
        }

        return $this->_get_actions[$id_acl_role][$id_resource];
    }

    protected $_get_actions = array();

    /**
     * Prepare data to delete roles rule
     * @param int $id_acl_role
     * @return boolean 
     */
    public function delete_rules($id_acl_role = 0) {
        // Prepare data
        $id_acl_role = intval($id_acl_role);

        // Get all $id_acl_role rules
        $rules = $this->db->
                        select('acl_rule.id_acl_rule, acl_resource.acl_resource_name, acl_action.acl_action_name')->
                        join('acl_resource', 'acl_resource.id_acl_resource=acl_rule.id_acl_resource', 'left')->
                        join('acl_action', 'acl_action.id_acl_action=acl_rule.id_acl_action', 'left')->
                        where('acl_rule.id_acl_role', $id_acl_role)->
                        get('acl_rule')->result_array();
        if (empty($rules)) {

            return FALSE;
        }

        // Get all allowed rules for current role from $rules
        foreach ($rules as $rule) {
            if ($this->rt_user->isAllowed($rule['acl_resource_name'], $rule['acl_action_name'])) {
                $this->_delete_rules[] = $rule['id_acl_rule'];
            }
        }
        if (empty($this->_delete_rules)) {

            return FALSE;
        }

        return TRUE;
    }

    protected $_delete_rules = array();

    /**
     * Prepare data to save roles rule
     * @param int $id_acl_role
     * @param int $id_acl_resource
     * @param int $id_acl_action
     * @return boolean 
     */
    public function add_rule($id_acl_role, $id_acl_resource, $id_acl_action) {
        // Access check
        $acl_resources = $this->get_acl_resources();
        $acl_actions = $this->get_actions($id_acl_role, $id_acl_resource);
        if (empty($acl_resources[$id_acl_resource]['acl_resource_name']) || empty($acl_actions[$id_acl_action]['acl_action_name']) || !$this->rt_user->isAllowed($acl_resources[$id_acl_resource]['acl_resource_name'], $acl_actions[$id_acl_action]['acl_action_name'])) {

            return FALSE;
        }

        // prepare data
        $this->_add_rule[] = array(
            'id_acl_role' => intval($id_acl_role),
            'id_acl_resource' => intval($id_acl_resource),
            'id_acl_action' => intval($id_acl_action)
        );

        return TRUE;
    }

    protected $_add_rule = array();

    /**
     * Save rules
     * @param int $id_acl_role
     * @return boolean
     */
    public function save_rules($id_acl_role) {
        $rs = FALSE;
        // Add new rules
        if (!empty($this->_add_rule)) {
            $this->db->insert_batch('acl_rule', $this->_add_rule);
            if ($this->db->insert_id() > 0) {
                $rs = TRUE;
            }
        }

        // Remove old rules
        if (!empty($this->_delete_rules)) {
            $this->db->
                    where_in('id_acl_rule', $this->_delete_rules)->
                    delete('acl_rule');
            if ($this->db->affected_rows() > 0) {
                $rs = TRUE;
            }
        }
        
        return $rs;
    }

    /**
     *  Callback functions for crud
     */
    public function callback_select_acl_role($name = '', $value = NULL) {
        $roles = $this->get_roles();
        $this->load->helper('form');
        $option = array();
        foreach ($roles as $role) {
            $option[$role['id_acl_role']] = $role['acl_role_name'];
        }

        return form_dropdown($name, $option, array($value));
    }

    public function callback_before_edit_user($post_data, $pkey) {
        $this->load->library('RT_user');
        if (isset($post_data['password'])) {
            $post_data['password'] = $this->rt_user->password_hash($post_data['password']);
        }

        $post_data['birth_date'] = date('Y-m-d', strtotime($post_data['birth_date']));
        $post_data['registered'] = date('Y-m-d', strtotime($post_data['registered']));

        // Disable deactivate current user
        if ($pkey == $this->rt_user->id_user) {
            $post_data['active'] = '1';
        }

        return $post_data;
    }

    private $acl_role_parent_id = array(0 => '---');

    public function get_parents($value = NULL) {
        // Get all parent id. SINGLETON
        if ($this->acl_role_parent_id == array(0 => '---')) {
            $current_role = intval($this->uri->get_next_segment('edit'));
            if ($current_role !== 0) {
                // Get all children
                $q = $this->db->
                                select('id_acl_role')->
                                where('active', '1')->
                                where('parent_id', $current_role)->
                                get('acl_role')->result_array();
                if (!empty($q)) {
                    $ids = array_map(function($v) {
                        return $v['id_acl_role'];
                    }, $q);
                    $ids[] = $current_role;
                    $this->db->where_not_in('parent_id', $ids);
                }
            }

            $temp = $this->db->
                            select('id_acl_role, acl_role_name')->
                            where('active', '1')->
                            where('id_acl_role <> ' . $current_role)->
                            order_by('acl_role_name', 'ASC')->
                            get('acl_role')->result_array();
            foreach ($temp as $v) {
                $this->acl_role_parent_id[$v['id_acl_role']] = $v['acl_role_name'];
            }
        }
        if ($value == NULL) {
            return $this->acl_role_parent_id;
        }

        return (!empty($this->acl_role_parent_id[$value])) ? $this->acl_role_parent_id[$value] : '';
    }

    /**
     * Callback function for parent_id
     * @param integer $value
     * @return string 
     */
    public function callback_acl_role_view_parent_id($value) {
        return $this->get_parents($value);
    }

    /**
     * Callback function for parent_id
     * @param integer $value
     * @return string 
     */
    public function callback_acl_role_edit_parent_id($name, $value = NULL) {
        $this->load->helper('form');

        return form_dropdown($name, $this->get_parents(), array($value));
    }

    public function prepare_password($post_data) {
        $this->load->library('RT_user');
        if (isset($post_data['password'])) {
            $post_data['password'] = $this->rt_user->password_hash($post_data['password']);
        }
        return $post_data;
    }

    public function callback_before_delete_role($ids) {
        $this->db->
                where_in('id_acl_role', $ids)->
                delete('acl_rule');

        return TRUE;
    }

    public function before_delete_user($items = array()) {
        $q = $this->db->
                        select('login')->
                        where_in('id_acl_user', $items)->
                        get('acl_user')->result_array();

        if (!empty($q)) {
            $this->acl_user_delete_observer->users = array_map(function($v) {
                return $v['login'];
            }, $q);
        }

        return TRUE;
    }

    /**
     * Create open form tag with actions buttons
     * @param string $action
     * @param array $attributes
     * @param array $hidden
     * @return string 
     */
    public function jq_action_form_open($action = '', $attributes = array(), $hidden = array()) {
        $this->load->helper('form');
        $this->ciext->load_jquery_ui();

        $content = array(
            'unique' => 'un' . rand()
        );

        $tpl = '<div class="ui-widget er_help" style="width:300px;float:right">
                    <div id="{unique}_status_error" style="padding: 0 .7em; display: none" class="ui-state-error ui-corner-all"><p><span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-alert"></span><label></label></p></div>
                    <div id="{unique}_status_highlight" style="padding: 0 .7em; display: none" class="ui-state-highlight ui-corner-all"><p><span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-info"></span><label></label></p></div>
                </div>
                <div class="resmng_content_panel">
                    <button id="{unique}_btn_save" class="btn_save">' . $this->lang->line('save_btn') . '</button>
                    <button id="{unique}_btn_cancel" class="btn_cancel">' . $this->lang->line('cancel_btn') . '</button>
                </div>
                <script type="text/javascript">
                $(function () {
                    $( "#{unique}_btn_save" ).button({
                        icons: {
                            primary: "ui-icon-disk"
                        }
                    }).click(function(){
                        $.post("' . $action . '", $("#{unique}").serialize(), function(data) {
                            r = jQuery.parseJSON(data);
                            if (r.status == 1) {
                                $("#{unique}_status_highlight label").html(r.status_message);
                                $("#{unique}_status_error").hide();
                                $("#{unique}_status_highlight").show().delay(3000).hide("normal");
                            } else {
                                $("#{unique}_status_error label").html(r.status_message);
                                $("#{unique}_status_highlight").hide();
                                $("#{unique}_status_error").show().delay(3000).hide("normal");
                            }
                        });
                        return false;
                    });
                    $( "#{unique}_btn_cancel" ).button({
                        icons: {
                            primary: "ui-icon-closethick"
                        }
                    }).click(function(){
                        $("#{unique}")[0].reset();
                        return false;
                    });
                });
                </script>';

        $attributes['id'] = $content['unique'];

        return form_open($action, $attributes, $hidden) . $this->parser->parse_string($tpl, $content, TRUE);
    }

}
