<?php

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

/**
 * Items interface
 * 
 * @author Igor Ratsun
 */
interface items {

    /**
     * Initialize 
     * @param array $ids
     */
    public function init($ids);

    /**
     * Create new item
     * @param string $name
     */
    public function create($name);

    /**
     * Get item name
     * @param int $id
     */
    public function get_name($id);

    /**
     * Get item alias
     * @param int $id
     */
    public function get_alias($id);

    /**
     * Get item content
     * @param int $id
     */
    public function get_content($id);

    /**
     * Set item name
     * @param int $id
     * @param string $name
     */
    public function set_name($id, $name);

    /**
     * Set content data
     * @param int $id
     */
    public function set_content($id);

    /**
     * Delete items to trash
     * @param array $ids
     */
    public function delete($ids);

    /**
     * Clone item
     * @param int $id
     * @param int $parent_id
     */
    public function clone_item($id, $parent_id);
}

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

    /**
     * Get items from result table and init needed items models
     * @param array $ids
     * @param int $deleted
     * @return array
     */
    protected function _get_items($ids = array(), $deleted = 0) {
        if (!empty($ids)) {
            if (count($ids) == 1) {
                $this->db->where('r.id_resource', intval(reset($ids)));
            } else {
                $this->db->where_in('r.id_resource', array_map('intval', $ids));
            }
        }

        if (!$this->rt_user->isAllowed('resmng', 'private')) {
            $this->db->where('private', FALSE);
        }

        // Get items from DB
        $res = $this->db->
                        select('r.id_resource, r.id_item, r.id_resource_type, r.position, rt.name, r.parent_id, r.private, rt.icon')->
                        where('r.id_resource_type = rt.id_resource_type')->
                        where('rt.active', TRUE)->
                        where('r.deleted', $deleted)->
                        order_by('r.parent_id, r.position', 'ASC')->
                        get('resource r, resource_type rt')->result_array();

        $item_types = array();
        foreach ($res as $v) {
            $item_types[$v['name']][] = $v['id_item'];
        }

        // Init items models
        foreach ($item_types as $type => $ids) {
            $model = 'item_' . $type . '_model';
            $this->load->model('resmng/' . $model);
            $this->{$model}->init($ids);
        }

        return $res;
    }

    /**
     * Get type of resource
     * @param int $id_resource_type
     * @return string
     */
    protected function _get_resource_type($id_resource_type = 0) {
        // Get single type
        if (!empty($id_resource_type)) {
            // Get resource type
            $type = $this->db->
                            select('name')->
                            where('id_resource_type', $id_resource_type)->
                            limit(1)->
                            get('resource_type')->row_array();

            return (!empty($type['name'])) ? $type['name'] : '';
        }

        // Get list
        $q = $this->db->
                        select('id_resource_type, name, alias, icon')->
                        where('active', TRUE)->
                        get('resource_type')->result_array();
        // Access check
        $access = array(
            'page_template' => 'edit_page_template',
            'page' => 'edit_page_content',
            'resource' => 'edit_resource_content',
        );
        $rs = array();
        foreach ($q as $item) {
            if (isset($access[$item['name']])) {
                if ($this->rt_user->isAllowed('resmng', $access[$item['name']])) {
                    $rs[] = $item;
                }
            } else {
                $rs[] = $item;
            }
        }
        
        return $rs;
    }

    protected function _get_child(&$data, $parent_id = 0) {
        $return = array();
        foreach ($data as $item) {
            if ($item['parent_id'] == $parent_id) {
                $return[] = $item['id_resource'];
                $children = $this->_get_child($data, $item['id_resource']);
                if (!empty($children)) {
                    $return = array_merge($return, $children);
                }
            }
        }

        return $return;
    }

    /**
     * Actions with trash
     * @param array $ids
     * @param int $action - 0: add to trash, 1: recovery, 2: clear
     * @return boolean
     */
    protected function _trash_actions($ids = array(), $action = 0) {
        // Prepare data
        $ids = (is_array($ids)) ? array_map('intval', $ids) : array(intval($ids));

        // Get ids with children ids
        $all_items = $this->_get_items(array(), ($action > 0));
        $new_ids = array();
        foreach ($ids as $id) {
            $new_ids[] = $id;
            $new_ids = array_merge($new_ids, $this->_get_child($all_items, $id));
        }
        $unique_ids = array_unique($new_ids);

        // Delete items
        if ($action == 2) {
            $search = array_flip($unique_ids);
            foreach ($all_items as $v) {
                if (isset($search[$v['id_resource']])) {
                    $item_ids[$v['name']][] = $v['id_item'];
                }
            }

            if (empty($item_ids)) {

                return FALSE;
            }

            foreach ($item_ids as $type => $value) {
                $this->{'item_' . $type . '_model'}->delete($value);
            }
        }

        // Change resource table
        $this->db->
                where_in('id_resource', $unique_ids);
        if ($action == 2) {
            $this->db->
                    where('deleted', 1)->
                    delete('resource');
        } else {
            $this->db->
                    update('resource', array('deleted' => ($action != 1)));
        }

        return ($this->db->affected_rows() > 0);
    }

    protected function _create_items_menu(&$data, $parent_id = 0) {
        $return = array();
        foreach ($data as $item) {
            if ($item['item_parent_id'] == $parent_id) {
                $children = $this->_create_items_menu($data, $item['id_resource']);
                $item['sub_level'] = (!empty($children)) ? 'class="sub-level ' . ((in_array($item['id_resource'], $this->convolute_items)) ? ' convolute' : '') . '"' : 'class="empty-level"';
                $item['children'] = $this->parser->parse('resmng/tree_menu', array('item' => $children), TRUE);
                $return[] = $item;
            }
        }

        return $return;
    }

    public function get_items($deleted = 0) {

        $show_private = $this->rt_user->isAllowed('resmng', 'private');

        // Get items data
        $rs = array();
        foreach ($this->_get_items(array(), $deleted) as $v) {
            $model = 'item_' . $v['name'] . '_model';
            $item_alias = $this->{$model}->get_alias($v['id_item']);
            $rs[] = array(
                'id_resource' => $v['id_resource'],
                'item_icon' => $v['icon'],
                'item_name' => $this->{$model}->get_name($v['id_item']),
                'item_title' => (!empty($item_alias)) ? 'id_' . $v['id_resource'] . ' : ' . $item_alias : 'id_' . $v['id_resource'],
                'item_parent_id' => $v['parent_id'],
                'item_private' => ($show_private) ? '<i class="' . (($v['private']) ? 'icon-eye-close' : 'icon-eye-open') . '"></i>' : ''
            );
        }

        return $rs;
    }

    protected $convolute_items = array();

    public function get_tree_menu($deleted = 0) {
        $items = $this->get_items($deleted);

        if ($deleted == 1) {
            foreach ($items as &$item) {
                $parent_id = 0;
                foreach ($items as $item1) {
                    if ($item1['id_resource'] == $item['item_parent_id']) {
                        $parent_id = $item['item_parent_id'];
                        break;
                    }
                }
                $item['item_parent_id'] = $parent_id;
            }
            unset($item);
        }

        // Get convolute items
        $this->load->library('ciext/configurator');
        $this->configurator->set_resource('resmng');
        $convolute = $this->configurator->get_config();
        if (isset($convolute['convolute']['user_' . $this->rt_user->id_user])) {
            $this->convolute_items = $convolute['convolute']['user_' . $this->rt_user->id_user];
        }

        return $this->_create_items_menu($items, 0);
    }

    public function get_tree_menu_context_menu($deleted = 0) {
        if ($deleted == 0) {
            $content = array();
            // Acceess check for create items
            $content['create_list'] = ($this->rt_user->isAllowed('resmng', 'create_element')) ? $this->_get_resource_type() : array();

            return $this->parser->parse('resmng/tree_menu_context_menu', $content, TRUE);
        }

        return $this->parser->parse('resmng/tree_menu_cart_context_menu', array(), TRUE);
    }

    public function create($name, $id_resource_type, $parent_id = 0) {
        // Prepare data
        $id_resource_type = intval($id_resource_type);
        $parent_id = intval($parent_id);

        // Get resource type
        $type = $this->_get_resource_type($id_resource_type);

        if (!$type) {

            return FALSE;
        }

        // Create item
        $model = 'item_' . $type . '_model';
        $this->load->model('resmng/' . $model);
        $item_id = $this->{$model}->create($name);

        // Create resource
        $this->db->
                insert('resource', array(
                    'id_item' => $item_id,
                    'id_resource_type' => $id_resource_type,
                    'parent_id' => $parent_id
        ));

        return $this->db->insert_id();
    }

    protected function _clone_item($id, $parent_id = NULL) {
        // Get item data
        $item = reset($this->_get_items(array($id), 0));

        if (empty($item)) {

            return FALSE;
        }

        $model = 'item_' . $item['name'] . '_model';
        $clone = $this->{$model}->clone_item($item['id_item'], $parent_id);

        if (!empty($clone)) {
            // Create resource
            $this->db->
                    insert('resource', array(
                        'id_item' => $clone,
                        'id_resource_type' => $item['id_resource_type'],
                        'parent_id' => (!is_null($parent_id)) ? $parent_id : $item['parent_id'],
                        'position' => (is_null($parent_id)) ? $item['position'] + 1 : $item['position'],
                        'private' => $item['private']
            ));
            
            $new_id = $this->db->insert_id();
            
            // Clone sub items
            $sub_items = $this->db->
                    select('id_resource')->
                    where('deleted', 0)->
                    where('parent_id', $id)->
                    get('resource')->result_array();
            if (!empty($sub_items)) {
                foreach ($sub_items as $row) {
                    $this->_clone_item($row['id_resource'], $new_id);
                }
            }

            return ($new_id > 0);
        }

        return FALSE;
    }

    public function clone_item($id) {
        // Prepare data
        $id = intval($id);

        if (empty($id)) {

            return FALSE;
        }
        
        // Clone main item
        return $this->_clone_item($id);
    }

    public function delete($ids = array()) {

        return $this->_trash_actions($ids, 0);
    }

    public function recovery($ids = array()) {

        return $this->_trash_actions($ids, 1);
    }

    public function clear_trash($ids = array()) {

        return $this->_trash_actions($ids, 2);
    }

    public function move($id = 0, $parent_id = 0, $position = 0) {
        // Update parent
        $this->db->
                where('id_resource', intval($id))->
                where('deleted', 0)->
                update('resource', array(
                    'parent_id' => intval($parent_id),
                    'position' => $position
        ));

        return ($this->db->affected_rows() > 0);
    }

    public function set_private($id = 0, $value = 0) {
        // Update private
        $this->db->
                where('id_resource', intval($id))->
                update('resource', array('private' => intval($value)));

        return ($this->db->affected_rows() > 0);
    }

    public function set_name($ids = 0, $name = '') {
        $item = reset($this->_get_items(array($ids)));

        return $this->{'item_' . $item['name'] . '_model'}->set_name($item['id_item'], $name);
    }

    public function get_content($id_resource = 0) {
        $item = reset($this->_get_items(array(intval($id_resource))));

        if (empty($item)) {
            return FALSE;
        }

        $item_content = $this->{'item_' . $item['name'] . '_model'}->get_content($item['id_item']);

        if ($item_content) {
            $this->load->helper('form');
            $lang = $this->lang->load('resmng/tabs');
            $content = array_merge(array(
                'form_open' => form_open('/ajax/resmng/resmng_admin/set_content', 'class="resmng_action_form"'),
                'hidden' => form_hidden('id_resource', $id_resource),
                'content' => $item_content,
                'form_close' => form_close()
                    ), $lang);

            return $this->parser->parse('resmng/action_container', $content, TRUE);
        } else {
            return FALSE;
        }
    }

    public function set_content() {
        $this->lang->load('resmng/tabs');

        $item = reset($this->_get_items(array(intval($this->input->post('id_resource')))));

        if (empty($item)) {
            $insert = 0;
        } else {
            $insert = $this->{'item_' . $item['name'] . '_model'}->set_content($item['id_item']);
        }

        $rs = array(
            'success' => intval($insert > 0),
            'msg' => ($insert) ? $this->lang->line('msg_saved') : $this->lang->line('msg_fail')
        );

        return json_encode($rs);
    }

}

