<?php
/**
 * config.php - Configuration feature. This is designed to support many systems/groups of configurations
 *
 * @author $Author: dtong $
 * @version $Id: config.php,v 1.16 2011/04/27 05:46:26 dtong Exp $
 * @copyright Copyright (c) 2011, Tiller Software Co., Ltd.
*/

require_once APPPATH . 'libraries/mapping/display_list.php';
require_once APPPATH . 'libraries/admin/config_data.php';
require_once APPPATH . 'libraries/admin/config_functions.php';
require_once APPPATH . 'libraries/admin/admin_loadconfig.php';

class Config extends CI_Controller {
	//app_config.value data field is 5000 chars
	const app_config_value_maxsize = 4998;

	private $config_functions;
	private $system_index=config_data::SYSTEM_GENERAL;
	private $last_handle_status=FALSE;

	function __construct() {
		parent::__construct();
		$this->access_model->checkaccess_any('admin_system_management');
		$this->load->helper('form');
		$this->load->model('admin/config_model');
		$this->load->model('sort/searchsort_model');
		$this->load->library('admin/admin_base');
		$this->load->library('form_validation');
		osa_load_lang('syscfg');
		$this->config_functions = new config_functions();
		osa_php_session_start();
	}

	function index($index=config_data::SYSTEM_GENERAL){
		$this->system_index = $index;
		$config_data = config_data::get_config($index);
		$data = new stdClass();
		$this->load->library('mapping/display_list');
		$display = $this->display_list;
		//$display->pagetitle = lang('admin_config_title');
		// Set column name
		$display->titles = array(lang('syscfg_title_name'), lang('syscfg_title_desc'),
									lang('syscfg_title_value'), '');

   	$display->widths = array('20%','55%','20%','5%');
		$display->sort_columns = FALSE;
		$display->allpage = TRUE;
		$display->cssclass_titlerow = 'table_head_col';
		$display->cssclass_datarow1 = 'table_body_row';
		$display->cssclass_datarow2 = 'table_body_row_none';
		$display->sort_refresh_divid_unqiue = TRUE;
		$data->display = $display;

		$this->load->view('template/html_output_view', array('html'=>'<div class="config_page">'));
		foreach ($config_data as $element) {
			//$value = $config_function->process();
			$row = $this->_get_display_row($element);
			if ( empty($row) ) {
				continue;
			}
			if ( !is_array($row) ) {
				//reset so it would update the total
				$display->reset();
				if ( $display->total > 0 ) {
					$this->load->view('mapping/display_list_view', $data);
				}
				$this->load->view('template/html_output_view', array('html'=>$row));
				$display->reset_data();
				continue;
			}
			$display->add($row);
		}
		//No need to save session.
		$display->no_session();
		$this->load->view('mapping/display_list_view', $data);
		$this->load->view('template/html_output_view', array('html'=>'</div>'));
	}

	//Shows the popup input page
	function edit($index, $item) {
		$this->system_index = $index;
		$config_data = config_data::get_config();
		$element = config_data::find($item);
		$data = new stdClass();
		if ( !$element ) {
			$data->errormsg = lang('gen_internalservererror');
			$data->divid = 'adminconfig';
			$this->load->view('template/ajax_error_view', $data);
			osa_errorlog(__METHOD__ . ' - failed to find item.', $item);
			return;
		}
		$data->name = $element[config_data::INDEX_PURPOSE];
		if ( array_key_exists(config_data::INDEX_DESC, $element) ) {
			$data->desc = $element[config_data::INDEX_DESC];
		}
		$data->use_boolean = FALSE;
		$data->use_textbox = FALSE;
		$data->use_multiline_textbox = FALSE;
		switch ($element[config_data::INDEX_TYPE]) {
			case config_data::TYPE_BOOLEAN:
				$data->use_boolean = TRUE;
				$data->boolean_negate = FALSE;
				break;
			case config_data::TYPE_BOOLEAN_NEGATE:
				$data->use_boolean = TRUE;
				$data->boolean_negate = TRUE;
				break;
			case config_data::TYPE_LONGSTRING: // (issue: 159) Add long-string type config
				$data->use_multiline_textbox = TRUE;
				$data->rowsize = config_data::INPUT_ROW_TEXT_SIZE;
				$data->textsize = config_data::INPUT_TEXT_SIZE; // $textsize is "cols", using "size" attributes from TYPE_STRING
				if ( array_key_exists(config_data::INDEX_ROW_TEXT_SIZE, $element) && $element[config_data::INDEX_ROW_TEXT_SIZE] !== FALSE ) {
					$data->rowsize = $element[config_data::INDEX_ROW_TEXT_SIZE];
				}
				if ( array_key_exists(config_data::INDEX_TEXT_SIZE, $element) && $element[config_data::INDEX_TEXT_SIZE] !== FALSE ) {
					$data->textsize = $element[config_data::INDEX_TEXT_SIZE];
				}
				break;
			default:
				$data->use_textbox = TRUE;
				$data->textsize = config_data::INPUT_TEXT_SIZE;
				if ( array_key_exists(config_data::INDEX_TEXT_SIZE, $element) && $element[config_data::INDEX_TEXT_SIZE] !== FALSE ) {
					$data->textsize = $element[config_data::INDEX_TEXT_SIZE];
				}
				break;
		}
		$data->machine_value = $this->_get_config_value($element, config_data::FORMAT_MACHINE_TYPE);
		$data->human_value = $this->_get_config_value($element);
		$data->item = $item;
		$data->index = $index;
		$data->show_default_button = TRUE;
		if ( array_key_exists(config_data::INDEX_NO_DEFAULT , $element) && $element[config_data::INDEX_NO_DEFAULT] ) {
			$data->show_default_button = FALSE;
		}
		if ( $this->last_handle_status == config_data::STATUS_REFRESH_PAGE ) {
			$data->refresh_page = TRUE;
		}
		$this->load->view('admin/config_input_view', $data);
	}

	//Sets the value back to the system default. This just deletes the DB value
	function set_default($index, $item) {
		$value = FALSE;
		$this->config_functions->value_handle($item, $value, config_data::ACTION_PREDELETE);
		$this->config_model->delete($item);
		$this->config_functions->value_handle($item, $value, config_data::ACTION_POSTDELETE);
		//$this->load_config($index);
		//$this->index($index);
	}

	//Does the update
	function update($index) {
		$this->system_index = $index;
		$this->form_validation->set_rules('item', '', 'required|trim');
		$this->form_validation->set_rules('value', '', 'required|trim');
		if ( !$this->form_validation->run() ) {
			echo osa_ajaxmsg(lang('syscfg_update_invalid_param'));
			exit;
		}
		$item = set_value('item');
		$value = set_value('value');
		$config_data = config_data::get_config($index);
		$element = config_data::find($item);
		if ( !$element ) {
			echo osa_ajaxmsg(lang('syscfg_update_invalid_param'));
			exit;
		}
		//Check and/or process incoming data according to the type
		switch($element[config_data::INDEX_TYPE]) {
			case config_data::TYPE_NUMERIC:
				if (!is_numeric($value) || $value <= 0) {
					echo osa_ajaxmsg(lang('syscfg_update_invalid_numeric'));
					exit;
				}
				break;
			case config_data::TYPE_INT:
				if ( !osa_is_int($value) || $value <= 0) {
					echo osa_ajaxmsg(lang('syscfg_update_invalid_integer'));
					exit;
				}
				break;
			case config_data::TYPE_BOOLEAN:
			case config_data::TYPE_BOOLEAN_NEGATE:
				if ( $value != '0' && $value != '1' ) {
					echo osa_ajaxmsg(lang('syscfg_update_invalid_param'));
					exit;
				}
				if ( $value == '0' ) {
					$value = FALSE;
				}
				else {
					$value = TRUE;
				}
				break;
			case config_data::TYPE_STRING:
			case config_data::TYPE_LONGSTRING:
				if ( strlen($value) > self::app_config_value_maxsize ) {
					echo osa_ajaxmsg(lang('syscfg_update_exceed_value_limit'));
					exit;
				}
				break;
			default:
				break;
		}
		$orig_value = $value;
		//Prewrite process if any
		$value = $this->config_functions->value_handle($item, $value, config_data::ACTION_PREWRITE);
		if (!$this->config_model->update($index, $item, $value)) {
			echo osa_ajaxmsg(lang('gen_internalservererror'));
			exit;
		}
		//Postwrite if any
		$this->config_functions->value_handle($item, $orig_value, config_data::ACTION_POSTWRITE);
		//Need to reload the config else it would use the old value
		$this->load_config($index);
		$this->index($index);
	}

	function update_header() {
		$this->load->view('template/header_view', array('user' => $this->login_model->getLogin()));
	}

	//Loads the config from DB into CI config
	private function load_config($index) {
		$load_config = new admin_loadconfig(FALSE);
		$load_config->load_config($index);
	}

	//Get one row of data for the display_list class
	private function _get_display_row($element) {
		if ( !is_array($element) || count($element) <= 0 ) {
			return FALSE;
		}
		$type = $element[config_data::INDEX_TYPE];
		switch ($type) {
			case config_data::TYPE_TITLE:
				return "<div class=\"config_group_title\">$element[1]</div>";
				break;
			default:
				$desc = '';
				if ( array_key_exists(config_data::INDEX_DESC, $element) ) {
					$desc = $element[config_data::INDEX_DESC];
				}
				$name = $element[config_data::INDEX_PURPOSE];
				//This will set the last_handle_status
				$value = $this->_get_config_value($element);
				/* if ($this->last_handle_status == config_data::STATUS_SKIP) {
					return FALSE;
				}*/
				/* This works too but the handle status above is much cleaner
				if ( $value === FALSE ) {
					//This is from the handle function telling to not display this row
					return FALSE;
				} */
				$editurl = base_url() . "admin/config/edit/{$this->system_index}/{$element[1]}";
				$wintitle = lang('syscfg_inputwin_title');
				$linktext = lang('syscfg_link_modify');
				$width = config_data::INPUT_WIN_WIDTH;
				$height = config_data::INPUT_WIN_HEIGHT;
				if ( array_key_exists(config_data::INDEX_WIN_WIDTH,$element) ) {
					if ($element[config_data::INDEX_WIN_WIDTH] !== FALSE) {
						$width = $element[config_data::INDEX_WIN_WIDTH];
					}
				}
				if ( array_key_exists(config_data::INDEX_WIN_HEIGHT,$element) ) {
					if ($element[config_data::INDEX_WIN_HEIGHT] !== FALSE) {
						$height = $element[config_data::INDEX_WIN_HEIGHT];
					}
				}
				$link = "<div style=\"text-align:center\">
						  <a style=\"color:blue\" href=\"{$editurl}\"
						  onClick=\"newDhtmlWindow('{$editurl}','{$wintitle}',{$width},{$height},'adminconfig');return false;\">{$linktext}</a></div>";
				//If the handle says disbale from last_handle_status then do it here
				switch ($this->last_handle_status) {
					case config_data::STATUS_BLANK_VALUE:
						$tmp = '<span style="color:grey">%s</span>';
						$name = sprintf($tmp, $name);;
						$desc = sprintf($tmp, $desc);
						$value = '';
						$link = '';
						break;
					case config_data::STATUS_SKIP:
						$tmp = '<span style="color:grey">%s</span>';
						$name = sprintf($tmp, $name);
						$desc = sprintf($tmp, $desc);
						$value = sprintf($tmp, $value);
						$link = '';
						break;
					case config_data::STATUS_DISABLE:
						return FALSE;
						break;
				}
				/*if ($this->last_handle_status == config_data::STATUS_DISABLE ||
					 $this->last_handle_status == config_data::STATUS_BLANK) {
					$tmp = '<span style="color:grey">%s</span>';
					$name = sprintf($tmp, $name);
					$desc = sprintf($tmp, $desc);
					$value = sprintf($tmp, $value);
					$link = '';
				}*/
				return array($name, $desc, $value, $link);
				break;
		}
	}

	//Gets the current config value. This relies on the autoload library.
	private function _get_config_value($element, $format=config_data::FORMAT_HUMAN_TYPE ) {
		static $config_functions = NULL;
		static $db_values = NULL;
		if ( $config_functions === NULL ) {
			$config_functions = $this->config_functions;
			//$db_values = $this->config_model->get_allconfig();
			//$db_values = FALSE;
		}
		/*
		if ($db_values && array_key_exists($element[config_data::INDEX_VAR], $db_values)) {
			//Process the value for display if necessary
			$value = $config_functions->value_handle($element[config_data::INDEX_VAR],
																  $db_values["{$element[config_data::INDEX_VAR]}"]);
			//So the calling function knows what to do
			$this->last_handle_status = $config_functions->last_status;
			if ( $format == config_data::FORMAT_MACHINE_TYPE ) {
				return $value;
			}
			return $this->_datatype_display_value($element[config_data::INDEX_TYPE], $value);
		} */
		$value = $config_functions->value_handle($element[config_data::INDEX_VAR],
															  $this->config->item("{$element[config_data::INDEX_VAR]}"));
		//So the calling function knows what to do
		$this->last_handle_status = $config_functions->last_status;
		//$value = $this->config->item("{$element[1]}");
		if ( $format == config_data::FORMAT_MACHINE_TYPE ) {
			return $value;
		}
		return $this->_datatype_display_value($element[config_data::INDEX_TYPE], $value);
	}

	//Modifys the value according to the data type for display purpose
	//This code can be in config_functions but don't want to have so many functions doing the same thing
	//So, have this function to process the generic stuff
	private function _datatype_display_value($type, $value) {
		switch($type) {
			case config_data::TYPE_BOOLEAN:
				if ( $value ) {
					return lang('syscfg_boolean_true');
				}
				return lang('syscfg_boolean_false');
				break;
			case config_data::TYPE_BOOLEAN_NEGATE:
				if ( !$value ) {
					return lang('syscfg_boolean_true');
				}
				return lang('syscfg_boolean_false');
				break;
			default:
				return $value;
				break;
		}
	}
}