<?php

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

class rtgc_set_relation_n_n
{

    protected $all_records = array();
    protected $selected_records = array();
    protected $field_name = '';
    protected $parent_table = '';
    protected $parent_table_id = 0;
    protected $selected_table = '';
    protected $mapping_table = '';
    protected $selected_table_alias_field = '';
    protected $selected_table_where = array();
    protected $selected_table_pkey = NULL;
    protected $parent_table_pkey = NULL;
    protected $linker_data = array();

    public function __construct($field_name, $parent_table = '', $parent_table_id = 0, $mapping_table = '', $selected_table = '', $selected_table_alias_field = '', $selected_table_where = array())
    {
        $this->select_data($field_name, $parent_table, $parent_table_id, $mapping_table, $selected_table, $selected_table_alias_field, $selected_table_where);
    }

    public function select_data($field_name, $parent_table, $parent_table_id, $mapping_table, $selected_table, $selected_table_alias_field, $selected_table_where)
    {
        $this->field_name = $field_name;
        $this->parent_table = $parent_table;
        $this->parent_table_id = $parent_table_id;
        $this->selected_table = $selected_table;
        $this->mapping_table = $mapping_table;
        $this->selected_table_alias_field = $selected_table_alias_field;
        $this->selected_table_where = $selected_table_where;
    }

    public function field($name)
    {
        $CI = & get_instance();
        $CI->load->helper('form');

        return form_multiselect($name . '[]', $this->get_all_records(), $this->get_selected_records(), 'class="multiselect"');
    }

    public function get_all_records()
    {
        if (empty($this->all_records)) {
            $selected_table_pkey = $this->get_selected_table_pkey();
            $CI = & get_instance();
            $db = clone $CI->db;
            foreach ($this->selected_table_where as $k => $v) {
                $db->where($k, $v);
            }
            $q = $db
                    ->select($selected_table_pkey . ',' . $this->selected_table_alias_field)
                    ->get($this->selected_table)
                    ->result_array();
            $all_records = array();
            foreach ($q as $item) {
                $all_records[$item[$selected_table_pkey]] = $item[$this->selected_table_alias_field];
            }

            $this->set_all_records($all_records);
        }

        return $this->all_records;
    }

    public function set_all_records($all_records)
    {
        $this->all_records = $all_records;
    }

    public function get_selected_records()
    {
        if (empty($this->selected_records)) {
            $selected_table_pkey = $this->get_selected_table_pkey();
            $parent_table_pkey = $this->get_parent_table_pkey();
            $CI = & get_instance();
            $db = clone $CI->db;
            $q = $db
                    ->select($selected_table_pkey)
                    ->where($parent_table_pkey, $this->parent_table_id)
                    ->get($this->mapping_table)
                    ->result_array();

            $selected_records = array();
            foreach ($q as $item) {
                $selected_records[$item[$selected_table_pkey]] = $item[$selected_table_pkey];
            }

            $this->set_selected_records($selected_records);
        }

        return $this->selected_records;
    }

    public function set_selected_records($selected_records)
    {
        $this->selected_records = $selected_records;
    }

    public function callback_before_edit($post, $pkey)
    {
        if (!empty($post[$this->field_name])) {
            $this->linker_data = array_map('intval', $post[$this->field_name]);
        }
        
        unset($post[$this->field_name]);

        return $post;
    }

    public function callback_after_edit($post_data, $pkey)
    {
        $CI = & get_instance();
        $db = clone $CI->db;

        $parent_pkey = $this->get_parent_table_pkey();
        $selected_table_pkey = $this->get_selected_table_pkey();

        // Clear old data
        $db->delete($this->mapping_table, array($parent_pkey => $pkey));
        
        // Add new data
        if (!empty($this->linker_data)) {
            $ins = array();
            foreach ($this->linker_data as $v) {
                $ins[] = array(
                    $parent_pkey => $pkey,
                    $selected_table_pkey => $v
                );
            }
            $db->insert_batch($this->mapping_table, $ins);
        }
        
        return TRUE;
    }

    protected function get_selected_table_pkey()
    {
        if (is_null($this->selected_table_pkey)) {
            $this->selected_table_pkey = $this->get_table_pkey($this->selected_table);
        }

        return $this->selected_table_pkey;
    }

    protected function get_parent_table_pkey()
    {
        if (is_null($this->parent_table_pkey)) {
            $this->parent_table_pkey = $this->get_table_pkey($this->parent_table);
        }

        return $this->parent_table_pkey;
    }

    protected function get_table_pkey($table)
    {
        $CI = & get_instance();
        $db = clone $CI->db;
        
        if ($db->dbdriver == 'postgre') {
            $pkey = $db->query('SELECT a.attname
                        FROM   pg_index i
                        JOIN   pg_attribute a ON a.attrelid = i.indrelid
                                             AND a.attnum = ANY(i.indkey)
                        WHERE  i.indrelid = \'' . $table . '\'::regclass
                        AND    i.indisprimary;'
            )->row_array();
            if (empty($pkey['attname'])) {
                show_error('Can not find primery key of table "' . $table . '"');
            }
            
            return $pkey['attname'];
        }
        
        $fields = $db->list_fields($table);

        if (empty($fields)) {
            show_error('Can not find primery key of table "' . $table . '"');
        }

        return reset($fields);
    }

}
