/**
 * @projectDescription Classes and functions for the locations module
 * 
 * @TODO 		--
 * @BUG/FIX		--
 * @author 		George Komianos
 * @copyright 	Acrodev.com - All rights reserved.
 * @version 	1
 * -------------------------------------------------------------------------- */

include_once(DIR_JS_URI + 'ajax.js');

/** 
 * 
 * @classDescription Performs various location specific methods.
 * -------------------------------------------------------------------------- */
function Locations ()
{
	this.Ajax 		= null;
	this.is_done 	= null;
	this.loc_type 	= null;
	this.loc_id 	= null;
	this.script_get = DIR_PHP_URI +'locations_get.php';
	
	/**
	 * Checks if a location is selected
	 * @param 	{Object} loc_type 
	 * @param 	{Object} elm_id - If not provided the default is assumed
	 * @return 	{Boolean}
	 */
	this.isSelected = function(loc_type, elm_id)	
	{
		if (elm_id == '') 
		{
			elm_id 	= loc_type+'_id';  // ie. region_id
		}
		
		if (this.getSelected(loc_type, 'id', elm_id) == 0)
		{
			this.setSelectMessages();
			return false;
		} 
		else {
			return true;
		}
	};
	
	this.setSelectMessages = function()	
	{
		this.select_region = 'Please select a region.';
		this.select_area = 'Please select an area.';
	};
	
	/**
	 * Retrieves the selected location
	 * If elm_id is not provided the default is assumed (region_id/area_id)
	 * 
	 * @param {String} loc_type - only required of elm_id is not provided
	 * @param {String} part - "id" to return the option's value or blank for its text
	 * @param {String} elm_id - only required if loc_type isn't provided
	 */
	this.getSelected = function(loc_type, part, elm_id) 
	{
		var self 	= Locations;
		
		if (elm_id == '') 
		{
			elm_id 	= loc_type+'_id';  // ie. region_id
		}
		
		var elm = document.getElementById(elm_id);
		
		if (part == 'id') 
		{
			return elm.options[elm.selectedIndex].value;	
		}
		else {
			return elm.options[elm.selectedIndex].text;
		}
	};
	
	/**
	 * It returns the value of the fist option of the specified location's
	 * dropdown box.
	 * If elm_id is not provided the default is assumed (region_id/area_id)
	 * @param {String} loc_type
	 * @param {String} elm_id - only required if loc_type isn't provided
	 */
	this.getFirst = function(loc_type, elm_id)
	{
		var self 	= Locations;
		
		if (loc_type == '') return false;
		
		if (elm_id == '') 
		{
			elm_id 	= loc_type+'_id';  // ie. region_id
		}
		
		var elm = document.getElementById(elm_id);
		
		return elm.value;
	};
	
	
	/**
	 * It refreshes the specified loc_type dropdown box.
	 * @see Ajax
	 * @param {Sting} loc_type
	 * @param {Integer} region_id - if provided only areas of this region are retrieved.
	 * @param {String} elm_id 	element to be refreshed if not provided the defaults are assumed (region_id/area_id)
	 */
	this.refreshList = function (loc_type, region_id, elm_id)
	{
		var self = Locations;
		
		var loc_type_var = 'loc_type='+loc_type;
		var post_data = '';
		post_data += 'loc_type='+loc_type;
		
		self.loc_type = loc_type;
		self.elm_id = elm_id;
		
		if (region_id) 
		{
			post_data += '&region_id='+region_id;
		}
		
		this.Ajax = new Ajax();
		
		this.Ajax.doPost(this.script_get, post_data, this.printOptions);
		this.setDone();
	};
	
	/**
	 * Checks repeatedly for Ajax request completion.
	 * It can be used to perform some action only after the Ajax request has
	 * been completed.
	 */	
	this.setDone = function ()
	{
		inter = setInterval(check, 30);
		
		var self = this;
		function check ()
		{
			var req_status = self.Ajax.req.readyState;
			if (req_status == 4) 
			{
				clearInterval(inter);
				self.is_done = 'ok';
			}
			else {
				self.is_done = 'no';	
			}
		}
	};
	
	/**
	 * Print/Update the location dropdown box with the values provided
	 * @param {String} str - String provided by Ajax (loc_id = loc_name)
	 * @return DOM manipulation
	 */
	this.printOptions = function (str)
	{
		var self = Locations;
		
		// specify external function as a property of this object
		self.locationsParse = locationsParse;
		var loc_array 	= self.locationsParse (str);
		
		var loc_type 	= self.loc_type;
		
		var elm_id = (self.elm_id) ? self.elm_id : loc_type+'_id';  // ie. region_id
		
		if (typeof document.getElementById (elm_id) == 'undefined') { return false; }
		
		var elm = document.getElementById (elm_id);
		
		if (!elm) return false;
		elm.options.length = 0; // delete current options
		
		var i = 0;
		var k = 0;
		
		for (description in loc_array) {
			if (loc_array[description] != 200) {
				k++;
			}
		}
		
		for(description in loc_array) 
		{  
			if (k >=1 && k != 1 && i<1) {
				elm.options[i] = new Option('-- All areas --', 0);
				i++;
			}
			
			elm.options[i] = new Option(description, loc_array[description]); // 'new text', 'new value'	
			i++;
		}
		
		self.loc_type = null;
		self.loc_id = null;
	};
	
	this.cleanup = function ()
	{
		var self 	= Locations;
		self.Ajax 	= null;
		self.str 	= null;
		self.is_done 	= null;
		self.loc_type 	= null;
		self.loc_id 	= null;
		self.region_id 	= null;
		self.post_data 	= null;
		this.select_region 	= null;
		this.select_area 	= null;
	};
}

/** 
 * @classDescription Adds a location and triggers appropriate post-addition action.
 * Refreshes the appropriate dropdowns or redirects to the "edit" page.
 * -------------------------------------------------------------------------- */
var Location_Add = new function () 
{
	this.Dialog 	= null;
	this.Ajax 		= null;
	this.loc_type	= null;
	this.add_type	= null;
	this.script_add	= DIR_PHP_URI +'location.php?action=add';
	this.script_refresh	= DIR_PHP_URI + 'locations_get.php';
	
	/**
	 * @param {String} loc_type
	 * @constructor
	 * @see Dialog
	 * @see Ajax
	 * @see Escape_Handler
	 */
	this.init = function(loc_type)
	{
		if (!objects_exist()) { return false; }
		
		var self = Location_Add;
		
		self.loc_type 	= loc_type;
		self.add_form 	= document.forms['add_'+self.loc_type+'_form']; // add_area_form
		
		self.loc_name = self.add_form[self.loc_type+'_name'];
		
		//this.setAddType();
		self.add_type = 'quick';
		
		self.Dialog 	= new Dialog();
		self.Ajax 		= new Ajax();
		self.initDialog();
		
		this.Esc = new Escape_Handler ();
		this.Esc.init(this.closeDialog);
	};
	
	
	this.initDialog = function()
	{
		var self = Location_Add;
		var Dialog = self.Dialog;
		
		if (this.checkRequired())
		{
			Dialog.init('Add Location');
			Dialog.resizeDialog('420');
			Dialog.addDialogPrompt();
			Dialog.addCancelButton(self.closeDialog);
			self.submitData();
		}
		else 
		{
			Dialog.init('Error');
			Dialog.resizeDialog('300');
			Dialog.addDialogPrompt();
			Dialog.setPrompt ("error", self.error);
			Dialog.addCancelButton(self.closeDialog);
		}
		
		self.dialog_body 	= Dialog.dialog_body;
		self.dialog_prompt 	= Dialog.dialog_prompt;
		self.msg_span 		= Dialog.msg_span;
		self.dot_span 		= Dialog.dot_span;
	};
	
	
	this.checkRequired = function()
	{
		var self = Location_Add;
		
		if (!self.loc_type)
		{
			self.error = 'The requested location type could not be retrieved.';
			return false;
		}
		
		// check empty name
		if (self.loc_name.value == '')
		{
			self.error = 'You did not specify a name.';
			return false;
		} 
		
		// check selected region
		if (self.loc_type == 'area') 
		{
			var region_id = self.add_form['region_id_new'];
			
			if (region_id.selectedIndex == 0) 	
			{
				self.error = 'You did not select a region.';
				return false;
			}
		}
		return true;
	};
	
	/**
	 * Set addition type according to description requirement.
	 * This dictates the addition and the post-addition methods.
	 */
	this.setAddType = function()
	{
		var self = Location_Add;
		
		var desc_id = 	(self.loc_type == 'region') ? 'add_reg_desc' : 
						(self.loc_type == 'area') ? 'add_area_desc' : 
						'';
		
		var desc = self.add_form[desc_id];
		self.add_type = (desc.checked) ? 'full' : 'quick';
	};
	
	/**
	 * Sets the data string for the Ajax request.
	 * @return string
	 */
	this.getFormData = function()
	{
		var self = Location_Add;	
	
		var btn_id = 	(self.loc_type == 'region') ? 'add_region' : 
						(self.loc_type == 'area') ? 'add_area' : 
						'';
						
		var post_data = formData2QueryString(self.add_form);
		post_data = post_data+ '&' +btn_id+ '=' +btn_id;
		return post_data;
	};
	
	/**
	 * @see Ajax
	 */
	this.submitData = function()
	{
		var self = Location_Add;
		var post_data = this.getFormData();
		
		self.Ajax.doPost(self.script_add, post_data, self.handleResponse);
		self.Dialog.showStatusPrompt();
	};	
	
	/**
	 * Sets the ajax response type and msg (success/error) and calls appropriate methods
	 * @param {String} str Response received
	 */
	this.handleResponse = function(str)
	{
		var self 		= Location_Add;
		// the response is in the following format
		// success, success string / error, error string
		var resp_arr 	= str.split(',');
		var resp_type 	= resp_arr[0].toLowerCase();
		var resp_msg 	= resp_arr[1];
		
		clearInterval(self.Dialog.prompt_interval);
		
		if (resp_type == 'success') 
		{
			if (self.add_type == 'quick') 
			{
				self.handleSuccess(resp_msg);
				
			}
			else if (self.add_type == 'full') 
			{
				self.handleSuccessFull(resp_msg);
			}
		}
		else {
			self.Dialog.setPrompt('err', resp_msg);
		}
	};
	
	/**
	 * Calls post "quick" addition actions.
	 * Displays success msg, and refreshes the locations' dropdow lists.
	 * @param {String} resp_msg - the success msg
	 */
	this.handleSuccess = function(resp_msg)
	{
		var self = Location_Add;
		
		self.Dialog.setPrompt('base', resp_msg);
		self.refreshLocations();
		
		// delete text entered in the addition form field
		var name_field = self.add_form[self.loc_type+'_name'];
		name_field.value = '';
	};
	
	/**
	 * Calls post "full" addition actions.
	 * Redirects to the new location's 'edit' page.
	 * @param {Integer} resp_msg - the id of the new location
	 */
	this.handleSuccessFull = function(resp_msg)
	{
		var self 		= Location_Add;
		var type_var 	= '&type='+ self.loc_type;
		var id_var 		= '&id='+ resp_msg;
		
		var url = 'index.php?action=edit'+type_var+id_var;
		
		window.location = url;
		this.closeDialog();
	};
	
	/**
	 * Refreshes the appropriate locations' dropdowns depending on the loc_type specified.
	 * @see Locations
	 */
	this.refreshLocations = function()
	{
		var locations = new Locations();

		locations.refreshList('region', '', '');
		
		// need to set up intervals between updates to avoid execution conflicts
		updateAreas ();
		function updateAreas ()
		{
			interval = setInterval(check, 20);
			
			function check ()
			{
				if (locations.is_done == 'ok')	
				{
					var region_id = locations.getFirst('region', '');
					locations.refreshList('area', region_id, '');
					clearInterval(interval);
					updateRegionNew ();
				}
			}
		}
		
		function updateRegionNew ()
		{
			interval = setInterval(check, 30);
			
			function check ()
			{
				if (locations.is_done == 'ok')	
				{
					locations.refreshList('region', '', 'region_id_new');
					clearInterval(interval);
					locations.cleanup();
				}
			}
		}
		
	};
	
	this.closeDialog = function() 
	{
		var self = Location_Add;
		self.Dialog.closeDialog();
		self.Dialog.cleanup();
		self.Esc.cleanup();
		self.cleanup();
		return true;
	};
	
	this.cleanup = function()
	{
		var self 		= Location_Add;
		self.Dialog 	= null;
		self.Ajax 		= null;
		self.locations 	= null;
		self.add_type	= null;
		self.the_form 	= null;
		self.btn1 		= null;
		self.btn2 		= null;
		self.btn_wrap 	= null;
		self.error	 	= null;
	};
};



/**
 * @classDescription Updates the area drop down box according to the region selected.
 * -------------------------------------------------------------------------- */
var Loc_Update_Areas = new function () 
{
	this.Locations = null;
	this.Ajax = null;
	this.regions_elm = null;
	this.areas_elm = null;
	
	/**
	 * Adds trigger
	 * @see Locations
	 * @constructor
	 */
	this.init = function() 
	{
		var self = Loc_Update_Areas;
		
		var regions_elm = getElement('','select', 'region_id');
	
		if (!regions_elm) { return false; }
		// Only proceed if the the region dropdown box has a class of "trigger"
		if (!regions_elm.className.match("trigger")) { return false; }
		
		regions_elm.onchange = function () 
		{
			self.indicateProcess();
			self.Locations 	=  new Locations();
			var region_id 	= self.Locations.getSelected('region', 'id', '');
			self.Locations.refreshList('area', region_id, '');	
		};
	};
	
	this.indicateProcess = function() 
	{
		var self = Loc_Update_Areas;
		
		self.areas_elm = getElement('','select', 'area_id');
		var areas_elm = self.areas_elm;
		
		areas_elm.options.length = 0;
		areas_elm.style.backgroundColor = '#f2f2f2';
		areas_elm.options[0] = new Option('Updating....', 0); // 'new text', 'new value'
		
		self.clearProcess();
	};
	
	this.clearProcess = function() 
	{
		var self = Loc_Update_Areas;
		
		var indicator_interval = setInterval(check, 10);
		self.indicator_interval = indicator_interval;
	
		function check ()
		{
			if (self.Locations.is_done == 'ok')	
			{
				clearInterval(self.indicator_interval);
				self.areas_elm.style.backgroundColor = '#ffffff';
				self.Locations.cleanup();
				self.cleanup();
			}
		}
	};
	
	this.clearIndicator = function ()
	{
		var self = Loc_Update_Areas;
					
		self.areas_elm.style.backgroundColor = '#ffffff';
		self.Locations.cleanup();
		self.cleanup();
	};
	
	this.cleanup = function() 
	{
		var self = Loc_Update_Areas;
		self.Locations = null;
		self.regions_elm = null;
		self.areas_elm = null;
	};
};


/**
 * Converts string with locations (01 = location name) to an array.
 * @param {String} str
 * @return {Array}
 * -------------------------------------------------------------------------- */
function locationsParse (str) 
{
	var loc_array = new Object();
	var arr = [];
	// match any non space character one or more times = 
	// any character one or more times (doesn't inlcude \n) 
	// globally
	var pat = /(\S+) = (.*)/g;
	
	while (arr = pat.exec(str)) 
	{
		loc_array[arr[2]] = arr[1];	
	}
	return loc_array;
}
	



/**
 * Attaches events for location search form
 * (show/hide region select box)
 */
function loc_attach_triggers_search ()
{
	var form = document.forms['loc-search'];
	
	if (!form) { return false; }
	
	var rs 		= Location_Search;
	rs.init();
	var region 	= form.elements['region'];
	var area 	= form.elements['area'];
	var btn		= form.elements['do_search']
	
	// make sure the form is in right 'state' on load
    if (region.checked == true)
    {
        hide('regions');
    }

    region.onclick = function () {
		hide('regions');
    };
    region.onkeypress = function () {
		hide('regions');
    };
	area.onclick = function () {
		show('regions');
    }
    area.onkeypress = function () {
		show('regions');
    };
	
	form.onsubmit = function () { return false; };
	
	btn.type = 'button';
	btn.onclick = function () 
	{
		rs.submitSearch('form');
    };
    btn.onkeypress = function () 
	{
		rs.submitSearch('form');
    };
}

/**
 * @classDescription Performs search and displays the results.
 * -------------------------------------------------------------------------- */
var Location_Search = new function () 
{
	this.script_get = DIR_PHP_URI +'locations_results.php';
	this.hist = [];
	this.histIndex = -1;
	
	/**
	 * @param {Object} trigger
	 * @constructor
	 */
	this.init = function(trigger) 
	{
		var self = Location_Search;
		
		self.container = getElement('','div', 'results');
		if (!self.container) { return false; }
		
		self.startHist();
	};
	
	this.submitSearch = function(trigger) 
	{
		var self = Location_Search;
		if (!self.container) { return false; }
		
		this.setData(trigger);
		this.getResults();
	};
	
	this.setData = function(trigger) 
	{
		var self = Location_Search;
		
		if (trigger == 'form')
		{
			var form = document.forms['loc-search'];
			var vars = formData2QueryString(form);
			// rename vars, so that they are the same with those used in
			// the php pagination class
			vars = vars.replace(/loc_type/, 'lt');
			vars = vars.replace(/description/, 'ds');
			vars = vars.replace(/review/, 'rv');
			vars = vars.replace(/publish/, 'pb');
			vars = vars.replace(/region_id/, 'rid');
			
			self.post_data = vars;
			set_cookie('loc_search', self.post_data, '', '', '', '');
		}
		else if (trigger.type = 'a')
		{
			var url = trigger.href;
			var mark = url.indexOf('?');
			self.post_data = url.substring(mark+1, url.length);
			set_cookie('loc_search', self.post_data, '', '', '', '');
		}
	};
	
	/**
	 * @see Ajax
	 */
	this.getResults = function() 
	{
		var self 	= Location_Search;
		this.Ajax 	= new Ajax();	
		this.Ajax.doPost(this.script_get, self.post_data, this.displayResults);
		this.showProcess();
	};
	
	/**
	 * @see Message_Prompt
	 */
	this.showProcess = function() 
	{
		var self 	= Location_Search;
		self.Prompt = new Message_Prompt();
		self.Prompt.init('', self.container, self.container.firstChild);
		self.Prompt.showStatus('');
	};
	
	this.handleData = function(str) 
	{
		var self = Location_Search;
		self.displayResults(str);
	};
	
	this.displayResults = function(str) 
	{
		var self = Location_Search;
	
		if (str == '' )
		{
			var txt = '<p class="hlight">There are no locations that fit the specified criteria.</p>';
			self.container.innerHTML = txt; 
		}
		else {
			self.container.innerHTML = '';
			self.container.innerHTML = str;
			self.updateHistory(str);
			self.addLinkTriggers();
		}
	};
	
	/**
	 * Adds triggers to links for pagination and sorting
	 */
	this.addLinkTriggers = function() 
	{
		var self = Location_Search;
		var node = document.getElementById('content-main');
		
		// add pagination triggers
		var uls = getElementsByClass ('pagination', node, 'ul');
		var ul 	= uls[0];
		var ls 	= getElements (ul, 'a');		
		var ln 	= ls.length;
		
		for (i = 0; i < ln; i++) 
		{
			var l = ls[i];
			l.onclick = function () 
			{
				self.submitSearch(this);
				return false;
			};
		}
		
		// add sort triggers
		var tb = getElement (node, 'table', 'locations');
		
		if (!tb) { return false; }
		
		var ls = getElementsByClass ('rv', tb, 'a');		
		var ln = ls.length;
		
		for (i = 0; i < ln; i++) 
		{
			var l = ls[i];
			l.onclick = function () 
			{ 
				self.submitSearch(this);
				return false;
			};
		}
		
		// add delete triggers
		var ls = getElementsByClass ('trigger-del', tb, 'a');
		var lg = ls.length;
		
		for (var i=0; i < lg; i++) 
		{
			var elm = ls[i];
			
			elm.onclick = function () 
			{
				var del = Location_Delete;
				del.init('', this, self.refreshResults);
				return false;
			};
		}
	};
	/**
	 * Retrieves and Refreshes the result table.
	 * It's called after successful deletion of a record.
	 */
	this.refreshResults = function()
	{
		var self = Location_Search;
		self.post_data = get_cookie('loc_search');
		alert(self.post_data);
		self.getResults();
	};
	
	/**
	 * @see SearchHistory
	 * @param {Object} str
	 */
	this.updateHistory = function(str) 
	{
		var self = Location_Search;
	    var maxLength = self.histIndex + 1;
	    var newHist = null;
	    
		while (self.hist.length > maxLength) 
		{
			self.hist.pop();
	    }
		
		if (!self.post_data) { self.post_data = ''; }
		if (!str) { str = ''; }
		
		newHist = new SearchHistory(self.post_data, str);
		self.hist.push(newHist);
		self.histIndex++;
		self.setHash(self.histIndex);
	  };
	  
	this.goBack = function() 
	{
		var self = Location_Search;
		self.histIndex--;
		self.showHistory();
	};
	  
	this.goForward = function() 
	{
	    var self = Location_Search;
	    self.histIndex++;
	    self.showHistory();
	};
	  
	this.showHistory = function() 
	{
		var self = Location_Search;
		var currHist = null;
		
		displayHist = self.hist[self.histIndex];
		self.updateForm(displayHist.terms);
		self.container.innerHTML = displayHist.results;
	};
	
	this.updateForm = function(terms) 
	{
		var form = document.forms['loc-search'];
		var regions = getElement(form, 'fieldset', 'regions');
		 
		var vars = terms.split('&');
		var l = vars.length;
		
		for (var i=0; i<l; i++)
		{
			var crumbs = vars[i].split('=');

			switch (crumbs[0])
			{
				case 'lt':
					if (crumbs[1] == 'region') 
					{
						var elm = 0;
						regions.style.display = 'none';
					}
					else {
						var elm = 1;
						regions.style.display = 'block';
					}
					form.elements['loc_type'][elm].checked = true;
					continue;
				
				case 'rid':
					form.elements['region_id'].value = crumbs[1];
					continue;
				
				case 'ds':
					form.elements['description'].value = crumbs[1];
					continue;
				
				case 'rv':
					form.elements['review'].value = crumbs[1];
					continue;
				
				case 'pb':
					form.elements['publish'].value = crumbs[1];
					continue;
			}
		}
	};
	  
	this.startHist = function() 
	{
		var self = Location_Search;
		var href = '';
		var ifr = null;
		
		if (document.all) 
		{
			ifr = document.createElement('iframe');
			ifr.name = 'historyFrame';
			ifr.id = 'historyFrame';
			ifr.src = '';
			ifr.style.display = 'none';
			document.body.appendChild(ifr);
		}
		
		if (location.hash) 
		{
			href = location.href.split('#')[0];
			location = href;
		}
		self.updateHistory();
		setInterval(self.watchHist, 100);
	};
	  
	this.setHash = function(val) 
	{
		if (val == 0) 
		{
			location.replace('#' + val);
		}
		else {
			location = '#' + val;
		}
		
		if (document.all) 
		{
			document.getElementById('historyFrame').src = 'blank.txt?' + val;
		}
	};
	  
	this.watchHist = function() 
	{
		var self = Location_Search;
		var href = '';
		var index = 0;
		var hash = '';
		
		if (document.all) 
		{
			var href = frames['historyFrame'].document.location.href;
			var hash = href.split('?')[1];
			var hash = (hash) ? ('#' + hash)  : '';
			
			if (hash && location.hash && (hash != location.hash)) 
			{
				location.replace(hash);
			}
		}
		
		var index = (location.hash) ? parseInt(location.hash.substr(1)) : -1;
		
		if (index != self.histIndex) 
		{
			self.goHistoryEntry(index);
		}
	};
		
	this.goHistoryEntry = function(val) 
	{
		var self = Location_Search;
		self.histIndex = val;
		self.showHistory();
	};
	
	this.cleanup = function() 
	{
		var self = Location_Search;
		self.Prompt.cleanup();
	};
};


// -- addEvents -- //
addEvent(window, "load", Loc_Update_Areas.init);


