<?php

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

/**
 * CRUD library
 *
 * @author Igor Ratsun
 */
class rtgrid_api {

    const VIEW_MODEL = 'rtgrid_model';
    const EDIT_MODEL = 'rtgrid_edit_model';

    protected $CI;
    protected $_adapter;

    public function __construct() {
        $this->CI = & get_instance();
        
        $this->CI->lang->load('rtgrid/api');
        $adapter_model = ($this->CI->uri->get_next_segment('edit') == 'add' || intval($this->CI->uri->get_next_segment('edit')) !== 0) ? self::EDIT_MODEL : self::VIEW_MODEL;

        // Add adapter
        $this->CI->load->model('rtgrid/' . $adapter_model);
        $this->_adapter = $this->CI->{$adapter_model};

        // Configurate if edit page
        if (!$this->is_grid()) {
            // Add primery key value
            $this->set_primery_key_value(intval($this->CI->uri->get_next_segment('edit')));
            $back_link = preg_replace('/\/edit\/[add\d]*$/', '', $this->CI->uri->uri_string());
            $this->add_action(new rtgrid_edit_action('back_to_list', $this->CI->lang->line('back_to_list'), '', '', '<a href="/' . $back_link . '" class="btn">{action_text}</a>'));
        }

        // Load bootstrap
        $this->CI->ciext->load_bootstrap();
    }

    /**
     * Set base table
     * @param string $table table name
     * @return void
     */
    public function set_table($table) {

        $this->_adapter->set_table($table);
        
        // Set primery key
        $this->set_primery_key('id_' . $table);
    }

    /**
     * Set primery key
     * @param type $primery_key primery key of base table
     * @return void
     */
    public function set_primery_key($primery_key) {

        $this->_adapter->set_primery_key($primery_key);
    }

    /**
     * Set alias to column/field
     * @param string $field column/field name
     * @param string $value alias
     * @return void
     */
    public function display_as($field, $value) {

        $this->_adapter->display_as($field, $value);
    }

    /**
     * Add where condition
     * @param mixed $key
     * @param string $value
     * @param boolean $escape
     * @return void
     */
    public function where($key, $value = NULL, $escape = TRUE) {

        $this->_adapter->where($key, $value, $escape);
    }

    /**
     * Add where_in condition
     * @param mixed $key
     * @param string $value
     * @param boolean $escape
     * @return void
     */
    public function where_in($key, $value = NULL, $escape = TRUE) {

        $this->_adapter->where_in($key, $value, $escape);
    }

    /**
     * Join other table
     * @param string $table
     * @param string $cond
     * @param string $type
     * @return void
     */
    public function join($table, $cond, $type = 'left') {

        $this->_adapter->join($table, $cond, $type);
    }

    /**
     * Default callback for field in grid and edit
     * @param string $field field name
     * @param mixed $default_callback callback for field
     * @return void
     */
    public function callback($field, $default_callback) {
        $model = 'rtgrid_field_callback';
        $adapter = 'callback_field';

        if ($this->is_grid()) {
            $model = 'rtgrid_column_callback';
            $adapter = 'callback_column';
        }

        // Load default callback model
        $this->CI->load->model('rtgrid/' . $model);
        if (method_exists($this->CI->{$model}, $default_callback)) {
            
            if (!$this->is_grid() && is_string($default_callback) && in_array($default_callback, array('date', 'datetime'))) {
            
                $this->_adapter->callback_before_edit(function($post, $pk) use($field){

                    $post[$field] = date('Y-m-d H:i:s', strtotime($post[$field]));

                    return $post;
                });
            }
            
            $this->_adapter->{$adapter}($field, array($this->CI->{$model}, $default_callback));
        }
    }

    /**
     * Add callback for field in edit
     * @param string $field field name
     * @param mixed $callback callback for field
     * @return void
     */
    public function callback_field($field, $callback) {
        if (!$this->is_grid()) {
            
            $this->_adapter->callback_field($field, $callback);
        }
    }
    
    /**
     * Add callback for column in grid
     * @param string $column column name
     * @param mixed $callback callback for field
     * @return void
     */
    public function callback_column($column, $callback) {
        if ($this->is_grid()) {
            
            $this->_adapter->callback_column($column, $callback);
        }
    }

    /**
     * Add action
     * @param rtgrid_top_action $rtgrid_action
     * @return void
     */
    public function add_action(rtgrid_top_action $rtgrid_action) {
        if ($rtgrid_action instanceof rtgrid_edit_action && !$this->is_grid()) {
            $this->_adapter->add_action($rtgrid_action);
        }

        if ($rtgrid_action instanceof rtgrid_top_action && $this->is_grid()) {
            $this->_adapter->add_action($rtgrid_action);
        }
    }

    /**
     * Remove action
     * @param string $rtgrid_action actino name
     * @return void
     */
    public function unset_action($action_name) {
        if ($this->is_grid()) {
            $this->_adapter->unset_top_action($action_name);
        }

        $this->_adapter->unset_action($action_name);
        
        // If unset edit and is edit page then show 404
        if ($action_name == 'edit' && !empty($this->CI->{self::EDIT_MODEL}) && $this->_adapter == $this->CI->{self::EDIT_MODEL}) {
            show_404('', FALSE);
        }
    }

    /**
     * Is grid page now?
     * @return boolean
     */
    public function is_grid() {
        $view = self::VIEW_MODEL;

        return ($this->_adapter instanceof $view);
    }

    /**
     * Add columns list
     * @param string $columns - Like 'name, surname, age'
     * @return void
     */
    public function columns($columns) {
        if ($this->is_grid()) {

            $this->_adapter->columns($columns);
        }
    }

    /**
     * Add fields list
     * @param string $fields - Like 'name, surname, age'
     * @return void
     */
    public function fields($fields) {
        if (!$this->is_grid()) {

            $this->_adapter->fields($fields);
        }
    }

    /**
     * Set relation 1:n
     * @param string $field_name field in base table
     * @param string $related_table related table
     * @param string $related_title_field field from relater table
     * @param mixed $where framework where. Optional
     * @param string $order_by ASC or DESC. Optional
     * @return void
     */
    public function set_relation($field_name, $related_table, $related_title_field, $where = NULL, $order_by = 'ASC') {
        $this->_adapter->set_relation($field_name, $related_table, $related_title_field, $where, $order_by);
    }

    /**
     * Add observer
     * @param SplObserver $obs
     * @return void
     */
    public function attach(SplObserver $obs) {

        $this->_adapter->attach($obs);
    }

    /**
     * Remove observer
     * @param SplObserver $obs
     * @return void
     */
    public function detach(SplObserver $obs) {

        $this->_adapter->detach($obs);
    }

    /**
     * Add multilang field
     * @param multilang $multilang
     * @return boolean
     */
    public function multilang(multilang $multilang) {

        return $this->_adapter->multilang($multilang);
    }
    
    /**
     * Add photogallery tab in edit
     * @param photogallery $photogallery photogallery configuration
     * @return void
     */
    public function add_photogallery(photogallery $photogallery) {
        
        $this->_adapter->add_photogallery($photogallery);
    }
    
    /**
     * Set base order by
     * @param string $column
     * @param string $direction
     */
    public function set_order_by($column, $direction = 'ASC') {
        if ($this->is_grid()) {
            
            $this->_adapter->set_order_by($column, $direction);
        }
    }
    
    /**
     * Add action before edit
     * @param callback $callback
     */
    public function callback_before_edit($callback) {
        if (!$this->is_grid()) {
            
            $this->_adapter->callback_before_edit($callback);
        }
    }
    
    /**
     * Set readonly field
     * @param string $field
     */
    public function readonly($field) {
        
        if (!$this->is_grid()) {
            $this->_adapter->readonly($field);
        }
    }
    
    
    public function set_image_upload(image_upload $data) {
        
        $this->_adapter->set_image_upload($data);
    }
    
    public function required_fields() {
        if (!$this->is_grid()) {
            $args = func_get_args();
            if (!empty($args)) {
                $this->_adapter->required_fields($args);
            }
        }
    }

        /**
     * Render CRUD
     * @return string ready html
     */
    public function render() {
        
        return $this->_adapter->render();
    }

    /**
     * Call other function of model
     * @param string $name
     * @param array $arguments
     * @return mixed
     */
    public function __call($name, $arguments) {
        if (method_exists($this->_adapter, $name)) {

            return call_user_func_array(array($this->_adapter, $name), $arguments);
        } else {

            show_error(sprintf($this->CI->lang->line('Method not found'), $name), 500);
        }
    }

}
