<?php
/**
 * util.php - Survey utility file.
 *
 * @author $Author: dtong $
 * @version $Id: util.php,v 1.13 2011/03/16 10:36:00 dtong Exp $
 * @copyright Copyright (c) 2010, Tiller Software Co., Ltd.
*/
require_once(APPPATH . 'libraries/mapping/display_list.php');

class Util extends CI_Controller {
	//Have file part so we can group surveys in the file system.
	//This is necessary if we need to have surveys other than for goal
	CONST SURVEY_FILE_PART = 'survey';
	//Can override this in config later
	private $blocks = FALSE;
	private $chart_width = 300;
	private $chart_height = 130;

	function __construct() {
		parent::__construct();
		//Make sure user has survey write access else it will exist
		$this->access_model->checkaccess_any('survey_write');
		osa_load_lang('survey');
		$this->load->model('survey/survey_model');
		$this->load->model('sort/searchsort_model');
		$this->load->library('form_validation');
		$this->load->helper('form');
		$this->blocks = $this->config->item('cms_survey_blocks');
	}

	//Lists surveys belonging to an external id. Only goals are supported for now
	function lists($extid) {
		$this->load->model('goal/goal_model');
		$goal = $this->goal_model->get_goal($extid);
		$surveys = $this->survey_model->get_survey_bygoalid($extid, TRUE);
		if ( !$goal || !$surveys ) {
			osa_errorlog(__METHOD__ . ' - Failed to get goal or survey.', array($goal, $surveys));
			echo lang('gen_internalservererror');
			return;
		}
		$data = new stdClass();
		if ( $surveys ) {
			$display = new display_list();
			$display->allpage = TRUE;
			$display->titles = array(lang('survey_list_table_title'),lang('survey_list_table_survey'),lang('survey_list_table_courses'),
											lang('survey_list_table_blocks'),lang('survey_list_table_url'),
											lang('survey_list_table_startdate'),lang('survey_list_table_enddate'),'&nbsp;');
			//$display->widths = array('20%', '17%', '8%', '29%', '8%', '8%', '10%');
			$display->widths = array('17%', '17%', '15%', '6%', '19%', '8%', '8%', '8%');
			$display->divid = 'page_content';
			$display->default_col = 0;
			$display->sort_columns = FALSE;

			$surveyid2title_references = $this->_prepare_template_titles($extid);

			$show_combine_checkbox = FALSE;
			if ( count($surveys) > 1 ) {
				$show_combine_checkbox  = TRUE;
			}
			foreach ($surveys as $record) {
				$courses = $this->survey_model->get_course_names($record->id);
				$blocks = $this->_get_blocks($record->id);
				//Link for the URL
				$survey_href = base_url() . $record->parity . dechex($record->id);
				$survey_url = "<a href=\"$survey_href\" target=\"_blank\" title=\"" . lang('survey_list_take_alt') .
								  "\"><font color=\"blue\">$survey_href</font></a>";
				//Edit link
				$edit_url =  base_url() . "survey/util/edits/$extid/{$record->id}";
				$jscript = "onClick=\"ajaxGetpage('page_content','" . "$edit_url',false);return false;\"";
				$edit_url = "<a href='$edit_url' $jscript title=\"" . lang('survey_list_edit_alt') . "\"><font color=\"blue\">" .
								lang('survey_list_edit') . "</font></a>";
				//Take link
				$take_url = "<a href='$survey_href' target=\"_blank\" title=\"" . lang('survey_list_take_alt') .
								"\"><font color=\"blue\">" . lang('survey_list_take') . "</font></a>";
				//Result link
				$result_url = base_url() . "survey/result/index/$record->id";
				//$jscript = "onClick=\"ajaxGetpage('page_content','" . "$result_url',false);return false;\"";
				$jscript = "onClick=\"survey_result('$result_url',{$this->chart_width},{$this->chart_height});return false;\"";
				$result_url = "<a href='$result_url' $jscript title=\"" . lang('survey_list_result_alt') . "\"><font color=\"blue\">" .
								lang('survey_list_result') . "</font></a>";

				$survey_title = '';
				if ( array_key_exists($record->id, $surveyid2title_references) ) {
					$survey_title = $surveyid2title_references[$record->id];
				}
				$combine_checkbox = '';
				if ( $show_combine_checkbox ) {
					$tmp_text = lang('survey_list_show_combined');
					$combine_checkbox = "<nobr><input type=\"checkbox\" name=\"combineid[]\" value=\"{$record->id}\" checked=\"checked\" />{$tmp_text}</nobr>";
				}
				$list_data = array($record->title, $survey_title, $courses, $blocks, $survey_url,
										 '<nobr>' . osa_date_format($record->startdate) . '</nobr>',
										 '<nobr>' . osa_date_format($record->enddate) . '</nobr>',
										 "<center>{$edit_url}&nbsp;{$take_url}&nbsp;{$result_url}</center>{$combine_checkbox}");
				$display->add($list_data);
			}
		}
		$data->show_combine_checkbox = $show_combine_checkbox;
		$data->display = $display;
		$data->title = sprintf(lang('survey_list_title'), $goal->title);
		$data->extid = $extid;
		$data->chart_width = $this->chart_width;
		$data->chart_height = $this->chart_height;
		$this->load->view('survey/survey_list_view',$data);
		//osa_previous_url("survey/util/lists/$extid");
		osa_url_history(CMS_URLHISTORY_SURVEYLIST, "survey/util/lists/$extid");
	}

	//Get the list of block names for a survey
	private function _get_blocks($surveyid) {
		$blocks = $this->survey_model->get_blocks($surveyid);
		$ret = '';
		$sep = '';
		if ( $blocks ) {
			foreach ($blocks as $record) {
				$ret .= $sep . $this->blocks[$record];
				$sep = ', ';
			}
		}
		return $ret;
	}

	//Edits a survey
	//extid is goalid for now. May be add more support later
	//There should be one survey per goal for now
	function edits($extid, $surveyid) {
		return $this->_edit_real($extid, TRUE, $surveyid);
	}

	//Brings up the page to add survey
	//extid is goalid for now. May be add more support later
	function adds($extid) {
		return $this->_edit_real($extid, FALSE);
	}

	//This handles the actual survey add and edit
	//extid is goalid for now
	private function _edit_real($extid, $is_edit, $surveyid=FALSE) {
		$data = new stdClass();
		$data->extid = $extid;
 		$user = $this->login_model->getLogin();
 		$mycourses = $this->survey_model->get_mycourses($user->id);
 		$other_courses = $this->survey_model->get_othercourses($mycourses);

 		//Set up the course array for dropdown
 		//Combines mycourses and other courses
 		$combined_array = array();
 		if ( $mycourses != FALSE ) {
	 		$combined_array['null1'] = lang('survey_mycourses_select');
	 		$combined_array['null2'] = '---------------------------';
	 		foreach($mycourses as $record) {
	 			$combined_array[$record->id] = $record->name;
	 		}
	 		$combined_array['null3'] = '';
	 		$combined_array['null4'] = lang('survey_othercourses_select');
	 		$combined_array['null5'] = '---------------------------';
 		}
 		if ( $other_courses != FALSE ) {
	 		foreach($other_courses as $record) {
	 			$combined_array[$record->id] = $record->name;
	 		}
 		}
 		$data->courses = $combined_array;
 		$data->selected_courses = array();
 		$data->blocks = $this->blocks;
 		$data->selected_blocks = array();
 		$data->startdate = '';
 		$data->enddate = '';
 		$data->is_edit = $is_edit;
 		$year = date('Y', time());
 		$data->title = sprintf(lang('survey_default_title'), $year);
 		$data->survey_selections = $this->_get_survey_list(self::SURVEY_FILE_PART);
 		if ( !$data->survey_selections ) {
 			osa_errorlog(__METHOD__ . " Failed to get survey templates.", self::SURVEY_FILE_PART);
			echo osa_ajaxmsg(lang('gen_internalservererror'));
			exit;
 		}
 		$data->survey_selections_size = count($data->survey_selections);
 		if ( $data->survey_selections_size <= 0 ) {
 			$data->survey_selections_size = 1;
 		}
 		elseif ($data->survey_selections_size > 10) {
 			$data->survey_selections_size = 10;
 		}
 		$data->survey_selected = '';

 		//This part deals with the edit action
 		if ( $is_edit ) {
 			if ( $surveyid ) {
 				$survey = $this->survey_model->get_survey($surveyid, FALSE);
 				if ( $survey ) {
 					$data->surveyid = $survey->id;
 					$data->title = $survey->title;
 				}
 			}
 			else {
 				//If no id then there should be one survey per goal.
 				//This is the old code and not used any more
				$survey = $this->survey_model->get_survey_bygoalid($extid);
 			}
			if ( !$survey ) {
				osa_errorlog(__METHOD__ . " Failed to get survey for goal id $extid");
				echo osa_ajaxmsg(lang('survey_failed_get_survey'));
				exit;
			}
			$hexcode = osa_hex_code($survey->parity, $survey->id);
			$data->survey_url = base_url() . $hexcode;
			$data->startdate = osa_date_format($survey->startdate);
			$data->enddate = osa_date_format($survey->enddate);
			$data->selected_blocks = $this->survey_model->get_blocks($survey->id);
			$data->selected_courses = $this->survey_model->get_courses($survey->id);
			$data->survey_selected = $this->_get_selected_template($survey->id);
			$data->survey_dirty = $this->survey_model->survey_has_results($survey->id);
			$data->selected_template_title = '';
			if ( $data->survey_dirty && array_key_exists($data->survey_selected, $data->survey_selections) ) {
				$data->selected_template_title = $data->survey_selections[$data->survey_selected];
			}
 		}
		$this->load->view('survey/survey_add_view',$data);
	}

	//Creates a new survey in the database
	function creates() {
		return $this->_update_real(FALSE);
	}

	//Updates an existing survey
	function updates() {
		return $this->_update_real(TRUE);
	}

	//The actual function create or update a ssurvey
	private function _update_real($is_update) {
		$this->form_validation->set_rules('startdate', lang('survey_startdate'),'trim|required|callback__checkdate');
		$this->form_validation->set_rules('enddate', lang('survey_enddate'), 'trim|required|callback__checkdate');
		$this->form_validation->set_rules('extid', 'Goal ID', 'trim|required|isnumeric');
		$this->form_validation->set_rules('surveyid', 'Survey ID', 'trim');
		$this->form_validation->set_rules('title', lang('survey_field_title'), 'trim|required');
		$this->form_validation->set_rules('template', lang('survey_field_survey'), 'trim|required');
		if ( !$this->form_validation->run() ) {
	      //Caused the client print an error window with the validation errors.
	    	echo osa_ajaxmsg(lang('survey_missing_input') . validation_errors());
	      exit;
	   }
	 	$selected_template = set_value('template');
		$system_templates = $this->_get_survey_list(self::SURVEY_FILE_PART, FALSE);
		if ( !$system_templates || !array_key_exists($selected_template, $system_templates) ) {
			echo osa_ajaxmsg(lang('gen_internalservererror'));
	      exit;
		}
		$survey_templates = $system_templates[$selected_template]['templates'];

		$startdate = set_value('startdate');
		$enddate = set_value('enddate');
		$extid = set_value('extid');
		$surveyid = set_value('surveyid');
		$title = set_value('title');
		$selected_courses = FALSE;
		$selected_blocks = FALSE;
		if ( array_key_exists('courses', $_REQUEST) ){
			$tmp = $_REQUEST['courses'];
			if ( is_array($tmp) ) {
				$selected_courses = $tmp;
			}
		}
		//Let's make sure the user didn't select any labels in the drop down.
		$bad_course_select = FALSE;
		if ( $selected_courses ) {
			foreach ( $selected_courses as $tmp_courseid ) {
				if ( !is_numeric($tmp_courseid) ) {
					$bad_course_select = TRUE;
					break;
				}
			}
		}
		if ( $bad_course_select ) {
			echo osa_ajaxmsg(lang('survey_course_select_error'));
			return;
		}

		if ( array_key_exists('blocks', $_REQUEST) ){
			$tmp = $_REQUEST['blocks'];
			if ( is_array($tmp) ) {
				$selected_blocks = $tmp;
			}
		}

		$user = $this->login_model->getLogin();
		if ( !$is_update ) {
			//Create new survey

			//2,3 are the types in survey_template table
			//Right, now we are hard coding this but later we can let the user choose the templates
			//All the interfaces should be written in a way that is easy to adopt to more than 1 group of surveys
			//$survey_templates = array(2=>'survey_2', 3=>'survey_3');

			$url_code = $this->survey_model->create_survey($user->id, $extid, $startdate, $enddate, $selected_courses, $selected_blocks, $survey_templates, $title);
			//Soemthing went wrong and survey not created
			if ( !$url_code ) {
				$vars = array($user->id, $extid, $startdate, $enddate, $selected_courses, $selected_blocks, $survey_templates);
				osa_errorlog(__METHOD__ . " - Failed to create survey.", $vars);
				echo osa_ajaxmsg(lang('survey_create_error'));
				return;
			}
			$data = new stdClass();
			//The URL for the survey so the teacher can hand it out to students
			$data->survey_url = base_url() . $url_code;
			$data->extid = $extid;
			$this->load->view('survey/finish_create_view', $data);
			return;
		}
		else {
			//Do update
			if ( $surveyid && is_numeric($surveyid) ) {
				$survey = $this->survey_model->get_survey($surveyid, FALSE);
			}
			else {
				$survey = $this->survey_model->get_survey_bygoalid($extid);
			}
			$ret = FALSE;
			$surveyid = '';
			//See if the current user is the survey or goal creator
			//This was done for (issue: 127) where the admin created the survey and the user can't modify the survey
			if ( !($is_creator = ($survey->creatorid == $user->id)) ) {
				//Not the survey owner so check for the parent goal creatorid
				$this->load->model('goal/goal_model');
				$goal_record = $this->goal_model->get_goal($extid);
				if ( $goal_record ) {
					$is_creator = ($goal_record->creatorid == $user->id);
				}
			}
			//Make sure user has permission to update
			if ( $survey && ($is_creator || $this->access_model->checkaccess_any_noexit('survey_admin_write')) ) {
				$ret = $this->survey_model->update_survey($survey->id, $startdate, $enddate, $selected_courses, $selected_blocks, $title, $survey_templates);
				$surveyid = $survey->id;
			}
			if ( !$ret ) {
				$vars = array($surveyid, $startdate, $enddate, $selected_courses, $selected_blocks);
				osa_errorlog(__METHOD__ . " - Failed to update survey.", $vars);
				echo osa_ajaxmsg(lang('survey_edit_error'));
				return;
			}
			//The calling javascript will always redirect back to the goal page regradless success or not
			echo osa_ajaxmsg(lang('survey_edit_success'));
			return;
		}
	}

	//For checking data date format
	//Callback has to be public. Copied from unit.php
	public function _checkdate($str) {
		if ( strlen($str) != 10 ) {
			$this->form_validation->set_message('_checkdate', lang('unit_invaliddate'));
		   return FALSE;
		}
		$pattern = '/[1-9][0-9][0-9][0-9]\-[0-1][0-9]\-[0-3][0-9]/';
		if ( preg_match($pattern, $str) ) {
		   return TRUE;
		}
		else {
			$this->form_validation->set_message('_checkdate', lang('unit_invaliddate'));
         return FALSE;
		}
	}

	//Gets the list of surveys, the return array can contain title and templates or just the title string
	//indexed by the survey group name such as survey, surveyls etc.
	private function _get_survey_list($file_pattern, $title_only=TRUE) {
		$file_match = CMS_TEMPLATEPATH_BUILDER . CMS_TEMPLATE_SURVEY_IDENTIFIER . '/' .
							 $this->config->item('cms_unit_org') . "_{$file_pattern}*.php";
		$files = glob($file_match);
		$file_array = array();
		foreach ($files as $filepath) {
			$file = basename($filepath);
			//This is like survey_2.php
			$file_part = osa_str_extract($file, '_', FALSE);
			if ( !$file_part ) {
				return FALSE;
			}
			//This is like survey_2
			$file_part = osa_str_extract($file_part, '.php', TRUE, FALSE);
			if ( !$file_part ) {
				return FALSE;
			}
			//This is like survey
			$file_group = osa_str_extract($file_part, '_', TRUE, FALSE);
			if ( !$file_group ) {
				return FALSE;
			}
			//This is like 2
			$file_number = osa_str_extract($file_part, '_', FALSE, FALSE);
			if ( !$file_number ) {
				return FALSE;
			}
			if ( !array_key_exists($file_group, $file_array) ) {
				@osa_load_template_obj($file_part, TRUE, CMS_TEMPLATE_SURVEY_IDENTIFIER, 'obj');
				$obj = "obj_$file_part";
				if ( !class_exists($obj) ) {
					//We couldn't load the template class
					osa_errorlog(__METHOD__ . ' - failed to load template object.', array($file_pattern, $file_part, $filepath));
					echo osa_ajaxmsg(lang('gen_internalservererror'));
					exit;
				}
				eval("\$config = $obj::get();");
				$file_array[$file_group] = array('title'=>$config->title, 'templates'=>array($file_number=>$file_part));
			}
			else {
				$tmp = $file_array[$file_group]['templates'];
				$tmp[$file_number] = $file_part;
				$file_array[$file_group]['templates'] = $tmp;
			}
		}
		osa_array_natsort($file_array, 'title', TRUE);
		if ( $title_only ) {
			//Just put the title in the array, this is for the drop down selection box
			$tmp_array = array();
			foreach($file_array as $key => $value) {
				$tmp_array[$key] = $value['title'];
			}
			$file_array = $tmp_array;
		}
		return $file_array;
	}

	//This is always one template since you can only give out one survey at a time
	private function _get_selected_template($surveyid) {
		if ( !($templates = $this->survey_model->get_templates($surveyid)) ) {
			return FALSE;
		}
		$template = $templates[0]->template;
		return osa_str_extract($template, '_');
	}

	//Returns an array with survey id being the index and the survey title (the one from the actual template)
	private function _prepare_template_titles($extid) {
		//Get all the related db templates
		$templates = $this->survey_model->get_templates_by_goalid($extid);
		//reindex using the surveyid, overrides the survey_2, survey_3, don't need the number just the survey part
		$templates = osa_reindex_result($templates, 'surveyid', 'template');
		//Get all the survey titles
		$survey_list = $this->_get_survey_list(self::SURVEY_FILE_PART);
		$ret_array = array();
		foreach ( $templates as $key => $template ) {
			$template = osa_str_extract($template, '_');
			if ( !$template ) {
				continue;
			}
			if ( array_key_exists($template, $survey_list)) {
				$ret_array[$key] = $survey_list[$template];
			}
		}
		return $ret_array;
	}
}