<?php
/**
 * Handle_base.php - The base abstract class for search handles
 *
 * @author $Author: dtong $
 * @version $Id: Handle_base.php,v 1.30 2011/05/09 04:48:53 dtong Exp $
 * @copyright Copyright (c) 2009, Tiller Software Co., Ltd.
*/
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
require_once ('configfactory.php');
require_once('display_list.php');

abstract class Handle_base {
	//const SELECT_ALL = 'all';

	protected $CI = NULL;
	protected $request = NULL;
	protected $searchid = NULL;
	protected $config = NULL;
	protected $searchdata = NULL;
	protected $no_gensel_msg = '';
	protected $params = NULL; //The orginal $params. Need this for a handle to call another handle. Else, DO NOT USE IT!

	function __construct($params) {
		$this->params = $params;
		//Always need to provide the request array and the unique searchid in the template
		if ( array_key_exists('request', $params) )
			$this->request = $params['request'];
		if ( array_key_exists('searchid', $params) )
			$this->searchid = $params['searchid'];
		//Make sure we have the minimum required selections. This will exist if fails
		$this->check_param();
		//Get the config template
		$this->config = configfactory::factory();
		//Find the data based on unique searchid _uniqueid
		if ( !$this->get_searchdata($this->searchid) ) {
			osa_errorlog(__METHOD__ . " - failed to find data for searchid {$this->searchid}", $this->config);
			echo osa_ajaxmsg(lang('gen_internalservererror'));
			exit;
		}
		$this->CI = & get_instance();
	   if ( !$this->CI->login_model->isAuthenticated() ) {
         echo osa_ajaxmsg_redirecthome(lang('gen_js_ajaxsessiontimeoutmsg'));
         exit;
      }
		osa_load_lang('mapping');
		$this->CI->load->model('mapping/calendar_model');
		$this->CI->load->model('mapping/standbench_model');
		$this->no_gensel_msg = lang('map_noselectmsg');
		$this->CI->load->model('sort/searchsort_model');
		$this->CI->load->model('mapping/publishunit_model');
		$this->CI->load->library('cms/memory_table/unit_cache_table', array('check_empty'=>TRUE));
   	$this->CI->unit_cache_table->auto_update_nodelay(); //Run the scheduled auto update if necessary
   	//For debugging purpose
   	$this->CI->output->enable_profiler($this->CI->config->item('cms_debug_enable_profiler'));
	}

	//All the classes have to implement this method else dynamic library loading will break
	//This method is responsible to present the view/html
	abstract public function process();

	/*
	 * Checks all the input params are present
	 */
	private function check_param() {
		if ( !is_array($this->request) || empty($this->searchid) ) {
			osa_errorlog(__METHOD__ . " - request or searchid is undefined");
			echo osa_ajaxmsg(lang('gen_internalservererror'));
			exit;
		}
	}

	/*
	 * Finds the search template data based on the search unique id
	 */
	private function get_searchdata($searchid) {
		foreach ($this->config->search as $page) {
			//var_dump($page);
			if (array_key_exists(1, $page)) {
				foreach ($page[1] as $item) {
					$type = osa_value($item, '_type', FALSE);
					if ( $type == 'search' ) {
						if ( osa_value($item, '_uniqueid', FALSE) == $searchid) {
							$this->searchdata = $item;
							//var_dump($item);
							return TRUE;
						}
					}
				}
			}
		}
		return FALSE;
	}

	/*
	 * Check to make sure it is a valid SQL order-by parameter like "courseid,unitid"
	 * Returns false if invalid format else returns the orignal string
	 */
	protected function valid_sortparam($sort) {
		if ( $sort === FALSE )
			return FALSE;
		if ( ! preg_match('/^[a-zA-Z]+[a-zA-Z\,]*[a-zA-Z]+$/', $sort) )
			return FALSE;
		return $sort;
	}

	/*
	 * Gets a value from the data that generates the input/selection page "_data"
	 */
	public function get_inputvalue($key) {
		if ( strpos($key, '_') !== 0 ) {
			$key = '_' . $key;
		}
		// (issue: 136)
		$single_divid = $this->CI->config->item('cms_mapping_divid');
		//This will overrid the mapping _divid/windowid according to cms_mapping_divid
		if ( !empty($single_divid) ) {
			if ( $key == '_divid' ) {
				return $single_divid;
			}
		}
		return osa_value($this->searchdata['_data'], $key, FALSE);
	}

	/*
	 * Gets a template value from the array for search
	 */
	public function get_templatevalue($key) {
		if ( strpos($key, '_') !== 0 )
			$key = '_' . $key;
		return osa_value($this->searchdata['_search_data'], $key, FALSE);
	}

	/*
	 * Gets a request variable. The request can be a saved search.
	 * Use "_" to destigush the request variables from other request variables
	 */
	protected function get_requestvalue($key) {
		if ( strpos($key, '_') !== 0 )
			$key = '_' . $key;
		$value = osa_value($this->request, $key, FALSE);
		//Checkboxes returns '' empty string so make it false
		if ( $value === FALSE || is_null($value) || $value == '')
			return FALSE;
		return $value;
	}

	/*
	 * Makes sure something was selected
	 */
	protected function validSelection($selections) {
		if (!is_array($selections))
			return FALSE;
		foreach ($selections as $selection) {
			if (is_numeric($selection) || preg_match('/^[0-9]+[0-9,]*[0-9]+$|^[0-9]*$/', $selection))
				return TRUE;
		}
		return FALSE;
	}

	/*
	 * Takes out separator "-------" selection and decides to keep the all selection or not
	 * The logic is that if there is any other selection then the all select should be delected
	 */
	protected function cleanSelections($selects) {
		if ( !is_array($selects) ) {
			return FALSE;
		}
		$ret = array();
		$multi_select = FALSE;
		foreach ($selects as $select) {
			if ( is_numeric($select) ) {
				if ($multi_select) {
					//Individual selections overrides selection all
					//multi select always come first in the array so it is ok to destroy the old array
					$ret = array();
					$multi_select = FALSE;
				}
				$ret[] = $select;
			}
			elseif( preg_match('/[0-9][0-9,]*[0-9]/', $select) ) {
				//This allows value like '1,22,33' to be added
				$ret[] = $select;
				$multi_select = TRUE;
			}
		}
		//Take out the all selection if there is other selections
		if (count($ret)>1 && $ret[0]==CMS_SELECT_ALL)
			unset($ret[0]);
		if ( count($ret) <= 0 )
			return FALSE;
		return $ret;
	}

	/*
	 * This is the function that gets the course, department and grade selection.
	 * Used in many searches. For searches besides calendar searches both $checkdate and $getunitid should be FALSE
	 * $checkdate = false - doesn't require month and year inputs
	 * $getunitid = false - gets courseid instead
	 */
	protected function get_calendar_query($checkdate=FALSE, $getunitid=FALSE, $status_array=FALSE) {
		//Get the inputs from request
		$courses = $this->cleanSelections($this->get_requestvalue('_courses'));
		$mycourses = $this->cleanSelections($this->get_requestvalue('_mycourses'));
		$grades = $this->cleanSelections($this->get_requestvalue('_grades'));
		$departments = $this->cleanSelections($this->get_requestvalue('_departments'));
		if ( ($tmp_month = $this->get_requestvalue('_month_selected')) &&
			  ($tmp_year = $this->get_requestvalue('_year_selected')) ) {
			$monthfrom = $tmp_month;
			$yearfrom = $tmp_year;
			$monthto = $tmp_month;
			$yearto = $tmp_year;
		}
		else {
			$monthfrom = $this->get_requestvalue('_month_from');
			$yearfrom = $this->get_requestvalue('_year_from');
			$monthto = $this->get_requestvalue('_month_to');
			$yearto = $this->get_requestvalue('_year_to');
		}
		$sort = $this->valid_sortparam($this->get_requestvalue('_sortorder'));
		//Check to see if we have the necessary selections.
		//It is ok as long as we can get at least one selection
		if ( !$this->validSelection($courses) && !$this->validSelection($mycourses) &&
				!$this->validSelection($grades) && !$this->validSelection($departments) ) {
			//echo osa_ajaxmsg(lang('map_noselectmsg'));
			echo osa_ajaxmsg($this->no_gensel_msg);
			exit;
		}
		//Check to make sure dates are present
		if ( $checkdate ) {
			if ( !$monthfrom || !$yearfrom || !$monthto || !$yearto ) {
				echo osa_ajaxmsg(lang('gen_internalservererror'));
				exit;
			}
			if ( $yearto < $yearfrom || ($yearto==$yearfrom && $monthto<$monthfrom)) {
				echo osa_ajaxmsg(lang('map_incorrect_daterange'));
				exit;
			}
		}
		//Get the DB query
		return $this->CI->calendar_model->get_query($courses, $mycourses, $grades, $departments, $sort,
														  $monthfrom, $yearfrom, $monthto, $yearto, $getunitid, $status_array);
	}

	//Loads the result view for all searches
	protected function load_view(&$display, $forcesort=FALSE) {
      $display->iswindow = TRUE;
      $display->force_sort = $forcesort;
      $display->prepare_page();
      $data = new stdClass();
      $data->display = $display;
      echo $this->CI->load->view('mapping/result_list_view', $data, TRUE);
      //$display->save_session();
	}

	//Generic URL link for opening up a unit page.
	//Requires 2 sprintf params in data[hide$INDEX] - EG: (10,10) , both are the unit id
	protected function get_unit_link() {
		$url = base_url() . "unit/unit/read/";
		// display_list::HIDEDATA_REPLACE_STR will be replaced with the unit title from the proper column from display_list->data
		$link = "<a class=\"cmslink\" href=\"{$url}%s\" onclick=\"newDhtmlWindow('{$url}%s','" . lang('map_unit') .
							"',900,800,'unitread');return false;\">" . display_list::HIDEDATA_REPLACE_STR . "</a>";
		return $link;
	}

	protected function get_courselt_link() {
		$url = base_url() . 'course/target/index_hist/%s';
		//lt_form divid is hardcoded for the close button
		return '<a class="cmslink" title="' . lang('map_lt_history_img_title') . '" ' .
				 "href=\"$url\" onClick=\"newDhtmlWindow('$url'," .
				 "'" . lang('map_lt_history_lnk_title') . "', 1000, 750, 'lt_form'); return false;\">" .
				 display_list::HIDEDATA_REPLACE_STR . "</a>";
	}

	protected function get_compare_link() {
		$url = base_url() . "unit/compare/current/%s";
		return "<a class=\"mapping_unitcompare\" href=\"$url\"
								onclick=\"newDhtmlWindow('$url','" . lang('map_unitcompare_title') .
								"',900,800,'compare');return false;\"><div class='mapping_unitcompare'>
								".lang('map_unitcompare_display')."</div></a>";
	}

	public function add_urllink_template_str($column_number, &$display, $url=FALSE) {
		if ( !is_object($display) ) {
			return FALSE;
		}
		if ( !$url ) {
			//Defaults to unit link since many searches use it
			return $display->add_urllink_template_str($column_number, $this->get_unit_link());
		}
		else {
			return $display->add_urllink_template_str($column_number, $url);
		}
	}

	public function add_hidden_data($column_number, &$data, $sprintf_values) {
		display_list::add_hidden_data($column_number, $data, $sprintf_values);
	}

	public function get_display_obj() {
		//Put it here so we can have more control and add whatever in the future
		return new display_list();
	}
}