/**
 * @author: RB
 * @date: 15-12-2008
 * @version: 1.0
 * 
 * @fileoverview:
 * Contains functionality for the search page of event finder
 * 
 */

// --------- PageRequestManager Events --------------

function clearPrmEndRequest() {
	
	prm.remove_endRequest(resetSearch_endRequestHandler);
	prm.remove_endRequest(getRecommended_endRequestHandler);
	prm.remove_endRequest(getResults_endRequestHandler);
}


function resetSearch_endRequestHandler(sender, args)
{
	setVenueSearchTypeByHdnField();
	updateResults();
}


function getRecommended_endRequestHandler(sender, args)
{       
	if (args.get_error() != undefined) {
		
		args.set_errorHandled(true);
		alert('The server request timed out');
		
		var recLoadingEl = document.getElementById('randrecloading');
		var recContainerEl = document.getElementById('randreccontainer');
		recContainerEl.removeChild(recLoadingEl);
	}
}


function getResults_endRequestHandler(sender, args)
{
	if (args.get_error() != undefined) {
		
		args.set_errorHandled(true);
		alert('The server request timed out');

		var loadingEl = document.getElementById('loadingmsg');
		var containerEl = document.getElementById('resultscontainer');
		containerEl.removeChild(loadingEl);
	}
}

// --------- End PageRequestManager Events ----------



var venueSearchType = {gardens: false,
					   allvenues: false,
					   avcache: {regionvenue: false, postcodevenue: false}};
					   
var updateOnRegionFocus = false;


function disableTbPostBack(e) {
	
	if (!e) var e = window.event;
	
	return !isEnterKey(e);
}


function resetSearch() {
	
	if (prm.get_isInAsyncPostBack()) {
		
		prm.abortPostBack();
	}
	
	// add end request event handler
	clearPrmEndRequest();
	prm.add_endRequest(resetSearch_endRequestHandler);
	
	doEfv2Postback('reset');
}


function setVenueSearchTypeByHdnField() {
	
	var el = document.getElementById(getFieldId('hdnSearchType'));
	
	if (el) {
		
		switch (el.value) {
			
			case 'gardens':
				setSearchGardens();
				break;
				
			case 'regionvenue':
				setSearchRegionVenue();
				
				var regionEl = document.getElementById(getFieldId('lbRegion'));
				if (regionEl) {
					removeClass(regionEl, 'disabledfield');
					updateVenuesByRegion(regionEl.value);
				}
				
				var pcodeEl = document.getElementById(getFieldId('txtPcode'));
				if (pcodeEl) addClass(pcodeEl, 'disabledfield');
				break;
				
			case 'postcodevenue':
				setSearchPostcodeVenue();
				
				var pcodeEl = document.getElementById(getFieldId('txtPcode'));
				if (pcodeEl) {
					removeClass(pcodeEl, 'disabledfield');
					updateVenuesByPostcode(pcodeEl.value);
				}
				
				var regionEl = document.getElementById(getFieldId('lbRegion'));
				if (regionEl) addClass(regionEl, 'disabledfield');
				break;
		}
	}
}


function fixRecommendedHeight() {
	
	var el = document.getElementById('randreccontainer');
	var innerDivEl = document.getElementById('randrecommended');
	var eventEls = innerDivEl.getElementsByTagName('div');
	
	// get the biggest offset height
	var height = 0;
	
	for (var i = 0; i < eventEls.length; i++) {
		if (eventEls[i].offsetHeight > height) {
			height = eventEls[i].offsetHeight;
		}
	}
	
	el.style.height = String(height) + 'px';
}


function fixResultsHeight() {
	
	var el = document.getElementById('resultscontainer');
	
	// only fix if there are currently results displayed
	if (el.offsetHeight > 0) {
		el.style.height = String(el.offsetHeight) + 'px';
	}
}


function resetVenueSearchType() {
	
	venueSearchType.gardens = false;
	venueSearchType.allvenues = false;
}


function resetAvCache() {
	
	venueSearchType.avcache.regionvenue = false;
	venueSearchType.avcache.postcodevenue = false;
}


function setSearchGardens() {
	
	resetVenueSearchType();
	venueSearchType.gardens = true;
}


function setSearchAllVenues() {
	
	resetVenueSearchType();
	venueSearchType.allvenues = true;
}


function keywordsChange(e) {
	
	if (!e) var e = window.event;
	
	if (isEnterKey(e)) updateResults();
}


function regionFocus(e) {
	
	if (!venueSearchType.allvenues || !venueSearchType.avcache.regionvenue ) {
		
		updateOnRegionFocus = true;
		
		setSearchRegionVenue();
		
		// set the postcode field to disabled style
		var el = document.getElementById(getFieldId('txtPcode'));
		addClass(el, 'disabledfield');
		
		if (!e) var e = window.event;
		var et = getEventTarget(e);
		
		removeClass(et, 'disabledfield');
		
		updateVenuesByRegion(et.value);
		updateResults();
	}
}


function postcodeFocus(e) {
	
	if (!venueSearchType.allvenues || !venueSearchType.avcache.postcodevenue ) {
		
		setSearchPostcodeVenue();
		
		// set the postcode field to disabled style
		var el = document.getElementById(getFieldId('lbRegion'));
		
		addClass(el, 'disabledfield');
		
		if (!e) var e = window.event;
		var et = getEventTarget(e);
		
		removeClass(et, 'disabledfield');
		
		updateVenuesByPostcode(et.value);
		updateResults();
	}
}


function setSearchRegionVenue() {
	
	resetVenueSearchType();
	resetAvCache();
	venueSearchType.allvenues = true;
	venueSearchType.avcache.regionvenue = true;
}


function setSearchPostcodeVenue() {
	
	resetVenueSearchType();
	resetAvCache();
	venueSearchType.allvenues = true;
	venueSearchType.avcache.postcodevenue = true;
}


function gpClickSetSearch() {
	
	setSearchGardens();
	updateResults();
}


function avClickSetSearch() {
	
	setSearchAllVenues();
	updateResults();
}


function allTypesClick(e) {
	
	if (!e) var e = window.event;
	var et = getEventTarget(e);
	
	var el = document.getElementById(getFieldId('pnlEventType'));
	
	if (el) {
		
		var els = el.getElementsByTagName('input');
		
		if (els) {
			
			for (var i = 0; i < els.length; i++) {
				
				if (els[i].type === 'checkbox') {
					els[i].checked = et.checked;
				}
			}
			
			updateResults();
		} 
	}
}


function regionChange(e) {
	
	if (!updateOnRegionFocus) {

		if (!e) var e = window.event;
		
		var et = getEventTarget(e);
		
		updateVenuesByRegion(et.value);
		
		updateResults();
	}
	else {
		updateOnRegionFocus = false;
	}
}


function updateVenuesByRegion(region) {
	
	// check we have the venues object on the client side
	if (venues) {
		// OK!
		
		// create empty array for filtered venues
		var filteredVenues = []; 
			
		for (var venue in venues) {
			
			if ((region === 'all') || (venues[venue].region === region)) {
				
				filteredVenues.push({Caption: venues[venue].caption, Value: venue});
			}
		}
		
		// get the venues field
		var listEl = document.getElementById(getFieldId('lbVenue'));
		
		// clear the list
		clearDisableList(listEl, false, 1, true);
		
		// add the new options to the list
		addListOptions(listEl, filteredVenues, 0);
	}
	else {
		alert('Could not get venues!');
	}
}


function postcodeChange(e) {
	
	if (!e) var e = window.event;
	
	var et = getEventTarget(e);
	
	updateVenuesByPostcode(et.value);
	
	// update the results if enter key is pressed
	if (isEnterKey(e)) updateResults();
	
	//updateResults();
}


function updateVenuesByPostcode(postcode) {

	// check we have the venues object on the client side
	if (venues) {
		
		// create empty array for filtered venues
		var filteredVenues = []; 
		
		// create regular expression to match the postcode
		var regEx = new RegExp('^' + postcode + '.*', 'i');
		
		// OK!
		for (var venue in venues) {
			
			if ((postcode === '') || (regEx.test(venues[venue].pcode))) {
				
				filteredVenues.push({Caption: venues[venue].caption, Value: venue});
			}
		}
		
		// get the venues field
		var listEl = document.getElementById(getFieldId('lbVenue'));
		
		// clear the list
		clearDisableList(listEl, false, 1, true);
		
		// add the new options to the list
		addListOptions(listEl, filteredVenues, 0);
	}
	else {
		alert('Could not get venues!');
	}
}


function dateFocus(e) {
	
	if (!e) var e = window.event;
	
	var et = getEventTarget(e);
	
	et.blur();
}


/**
 * quickDatesNw
 * 
 */
function quickDates(numWeeks) {
	
	var dateNow = new Date();
	
	var dayOfWeek = dateNow.getUTCDay();
	
	var dateNowMils = Date.UTC(dateNow.getUTCFullYear(), dateNow.getUTCMonth(), dateNow.getUTCDate());
	
	var startMils = dateNowMils + convertToMils((6 - dayOfWeek) + 1);
	var endMils = startMils + convertToMils(7 * numWeeks);
	
	var startDate = new Date();
	var endDate = new Date();
	
	startDate.setTime(startMils);
	endDate.setTime(endMils);
	
	var startDateEl = document.getElementById(getFieldId('txtStartDate'));
	var endDateEl = document.getElementById(getFieldId('txtEndDate'));
	
	if (startDateEl) {
		startDateEl.value = convertDateToString(startDate);
	}
	
	if (endDateEl) {
		endDateEl.value = convertDateToString(endDate);
	}
	
	// update the results
	updateResults();
	
	return false;
}


function convertToMils(days) {
	
	var miliseconds = days * 24 * 60 * 60 * 1000;
	return miliseconds;
}


/**
 * startDateChange
 * 
 */
function startDateChange(e) {
	
	if (!e) var e = window.event;
	
	var et = getEventTarget(e);
	
	// parse the start date
	var startDate = parseDate(et.value);
	
	var dateNow = new Date();
	dateNow.setUTCHours(0, 0, 0, 0);
	
	if ((startDate - dateNow) < 0) {
		
		alert('Start date cannot be before today');
		
		et.value = convertDateToString(dateNow);
	}
	
	var endDateEl = document.getElementById(getFieldId('txtEndDate'));
	
	if (endDateEl) {
		
		if (endDateEl.value !== '') {
			
			var endDate = parseDate(endDateEl.value);
			
			if ((endDate - startDate) < 0) {
				
				endDateEl.value = et.value;
			}
		}
		/*else {
			endDateEl.value = et.value;
		}*/
	}
	
	// update the results
	updateResults();
}


/**
 * endDateChange
 * 
 */
function endDateChange(e) {
	
	if (!e) var e = window.event;
	
	var et = getEventTarget(e);
	
	var startDateEl = document.getElementById(getFieldId('txtStartDate'));
	
	// parse the end date
	var endDate = parseDate(et.value);
	
	var dateNow = new Date();
	dateNow.setUTCHours(0, 0, 0, 0);
	
	if ((endDate - dateNow) < 0) {
		
		alert('End date cannot be before today');
		
		if (startDateEl && (startDateEl.value !== '')) {
			
			et.value = startDateEl.value;
		}
		else {
			et.value = '';			
		}
		
		return false;
	}
	
	if (startDateEl) {
		
		if (startDateEl.value !== '') {
			
			// parse the start date
			var startDate = parseDate(startDateEl.value);
			
			if ((endDate - startDate) < 0) {
				
				alert('End date cannot be before the start date');
				et.value = startDateEl.value;
			}
		}
		/*else {
			startDateEl.value = et.value;
		}*/
	}
	
	// update the results
	updateResults();
}


/**
 * clearStartDate
 * 
 */
function clearStartDate() {
	
	var el = document.getElementById(getFieldId('txtStartDate'));
	
	if (el && (el.value !== '')) {
		
		el.value = '';
		updateResults();
	}
}


/**
 * clearEndDate
 * 
 */
function clearEndDate() {
	
	var el = document.getElementById(getFieldId('txtEndDate'));
	
	if (el && (el.value !== '')) {
		
		el.value = '';
		updateResults();
	}
}


/**
 * parseDate
 * 
 * parses a string representation of a date into a javascript date object
 * NB. assumes a date format of dd/MM/yyyy
 * 
 * @param date: string: the date string to parse
 * 
 * @return Date: the javascript date object generated from the string
 * 
 */
function parseDate(date) {
	
	var dateArr = date.split('/');
	
	return new Date(parseInt(dateArr[2], 10), (parseInt(dateArr[1], 10) - 1), parseInt(dateArr[0], 10));
}


/**
 * convertDateToString
 * 
 * converts a javascript date object to a string in the format dd/MM/yyyy
 * 
 * @param date: Date: the date to convert
 * 
 * @return string: the string version of the date
 * 
 */
function convertDateToString(date) {
	
	var day = String(date.getUTCDate());
	day = (day.length === 1) ? ('0' + day) : day;
	
	var month = String(date.getUTCMonth() + 1);
	month = (month.length === 1) ? ('0' + month) : month;
	
	var year = String(date.getUTCFullYear());
	
	return day + '/' + month + '/' + year;
}


function randomizeRecommended() {
	
	if (document.getElementById('randrecommended')) {

		// fix the results height
		fixRecommendedHeight();
		
		// hide current recommended events
		Effect.Fade('randrecommended');
	}
	
	setTimeout(getRecommended, 1000);
}


function getRecommended() {	
	
	if (!checkForElement('randrecloading')) {
		
		showLoading();			
	}
	
	// add end request event handler
	clearPrmEndRequest();
	prm.add_endRequest(getRecommended_endRequestHandler);
	
	doEfv2Postback('randomrec');
	
	
	function showLoading() {
		
		var loadingEl = document.createElement('div');
		loadingEl.id = 'randrecloading';
		loadingEl.className = 'resultsloading';
		
		var randRecEl = document.getElementById('randreccontainer');
		randRecEl.appendChild(loadingEl);
		
		var imgEl = document.createElement('img');
		imgEl.src = './images/loaders/loader_green.gif';
		imgEl.alt = 'Refreshing Recommended Events...';
		loadingEl.appendChild(imgEl);
	}
}


/**
 * openRegionMap
 * 
 * opens a map showing venues in a particular region
 * 
 */
function openRegionMap() {
	
	var regionEl = document.getElementById(getFieldId('lbRegion'));
	
	var region = regionEl.value;
	
	if (region == 'all') {
		alert('Please select a region');
	}
	else {
		
		// check we have the venues object on the client side
		if (venues) {
			// OK!
			
			// create empty array for filtered venues
			var filteredVenues = []; 
				
			for (var venue in venues) {
				
				if (venues[venue].region == region) {
					
					filteredVenues.push({caption: venues[venue].caption, address: venues[venue].address + ' ' + venues[venue].pcode});
				}
			}
			
			initGoogleMapOverlay();
			
			if (gmapo) {
				
				gmapo.Config.mapCaption = 'Region: ' + ((regions) ? regions[region] : region) + '&nbsp;&nbsp;|&nbsp;&nbsp;Venue: All Venues';
				
				for (var i = 0; i < filteredVenues.length; i++) {
					
					gmapo.addAddress(filteredVenues[i].caption, filteredVenues[i].address);
				}
	            
	            gmapo.load();
			}
			else {
				alert('Could not initialise maps!');
			}
		}
		else {
			alert('Could not get venues!');
		}
	}
}


/**
 * openVenueMap
 * 
 * opens a map showing venue location
 * 
 */
function openVenueMap() {
	
	var venueEl = document.getElementById(getFieldId('lbVenue'));
	
	var venue = venueEl.value;
	
	if (venue == 'all') {
		alert('Please select a venue');
	}
	else {

		// check we have the venues object on the client side
		if (venues && venues[venue]) {
			// OK!
			
			initGoogleMapOverlay();
			
			if (gmapo) {
				
				gmapo.Config.mapCaption = 'Region: ' + ((regions) ? regions[venues[venue].region] : venues[venue].region) + '&nbsp;&nbsp;|&nbsp;&nbsp;Venue: ' + venues[venue].caption;
				gmapo.addAddress(venues[venue].caption, venues[venue].address + ' ' + venues[venue].pcode);
	            gmapo.load();
			}
			else {
				alert('Could not initialise maps!');
			}
		}
		else {
			alert('Could not get venue!');
		}
	}
}


function updateResults() {
	
	if (prm.get_isInAsyncPostBack()) {
		
		// cancel the current asynchronous request
		prm.abortPostBack();
		
		getResults();
	}
	else {
		
		// fix the results height
		fixResultsHeight();
		
		// hide current displayed results
		Effect.Fade('numresults');
		//if (document.getElementById('allresults')) Effect.Fade('allresults');
		Effect.Fade('recnumresults');
		//if (document.getElementById('recresults')) Effect.Fade('recresults');
		if (document.getElementById('results')) Effect.Fade('results');
		
		setTimeout(getResults, 1000);
	}
}


function getResults() {	
	
	var el = document.getElementById(getFieldId('hdnSearchType'));
	if (el) {
		
		// check again
		if (prm.get_isInAsyncPostBack()) {
			
			prm.abortPostBack();
		}
		
		if (!checkForElement('loadingmsg')) {
			
			showLoading();			
		}
		
		var type = (venueSearchType.gardens ? 'gardens' : (venueSearchType.avcache.regionvenue ? 'regionvenue' : 'postcodevenue'));
		el.value = type;
		
		// add end request event handler
		clearPrmEndRequest();
		prm.add_endRequest(getResults_endRequestHandler);
		
		doEfv2Postback('search');
	}
	
	
	function showLoading() {
		
		var loadingEl = document.createElement('div');
		loadingEl.id = 'loadingmsg';
		loadingEl.className = 'resultsloading';
		
		var containerEl = document.getElementById('resultscontainer');
		containerEl.appendChild(loadingEl);
		
		var img = document.createElement('img');
		img.src = './images/loaders/loader_orange.gif';
		img.alt = 'Refreshing Results...';
		loadingEl.appendChild(img);
	}
}


/**
 * getFieldId
 * 
 * returns the client id of an element based on it's ASP.NET server id
 * 
 * @param serverId: string: the ASP.NET server ID of the required element
 * 
 * @return string: the client id of the required element
 * 
 */
function getFieldId(serverId) {
	
	var clientId = '';
	
	if (fieldIds[serverId]) clientId = fieldIds[serverId].clientId;
	
	return clientId;
}


// ---------------- UTILITY FUNCTIONS -------------------------------------

/**
 * getEventTarget
 *
 * gets the target element of the event
 * 
 * @param e: object: the event
 * 
 * @return object: the target element of the event
 * 
 */
function getEventTarget(e) {

	if (e.target) {
		et = e.target;
	}
	else if (e.srcElement) {
		et = e.srcElement;
	}
	
	// Safari bug
	if (et.nodeType == 3)
		et = et.parentNode;
		
	return et;
}


/**
 * isEnterKey
 *
 * checks whether the event was triggered from an enter key press
 * 
 * @param e: object: the event
 * 
 * @return boolean: was the event triggered by an enter key press?
 * 
 */
function isEnterKey(e) {
	
	var code;
	
	if (e.keyCode) {
		code = e.keyCode;
	}
	else if (e.which) {
		code = e.which;
	}
	
	// the magic number - enter
	if (code == 13) {
		return true;
	}
	
	return false;
}


/**
 * clearDisableList
 * 
 * clears a specified select element and disables as required
 * 
 * @param list: object: the select element to clear
 * @param disable: boolean: indicates whether the list should be disabled
 * @param standardOptions: integer: specifies how many standard options the list has that shouldn't be removed
 * 
 */
function clearDisableList(list, disable, standardOptions, selectFirst) {
	
	var setDisabled = disable || false;
	var numStandardOptions = standardOptions || 1;
	
	if (list.options.length > 1) {
		for (var i = (list.options.length - 1); i > (numStandardOptions - 1); i--) {
			
			list.options[i] = null;
		}
	}
	
	// if required select the first option
	if (selectFirst) {
		list.options[0].selected = 'selected';
	}
	
	// if required disable the list
	if (setDisabled) {
	
		list.disabled = true;
	}
}


/**
 * addListOptions
 * 
 * adds passed options to the specified select element
 * 
 * @param list: object: the select element to add options to
 * @param options: array: array of objects containing caption and value for each option to be added 
 * 
 */
function addListOptions(list, options, selected) {
	
	for (var i = 0; i < options.length; i++) {
		
		list.options[list.options.length] = new Option(options[i].Caption, options[i].Value);
	}
}


/**
 * addClass
 * 
 * adds a css class to an element
 * 
 * @param el: DOM element: the element to add the css class to
 * @param className: string: the css class to add
 * 
 */
function addClass(el, className) {

	// remove first if it exists
	removeClass(el, className);
	
	if (el.className === '') {
		
		el.className = className;
	}
	else {
		el.className += ' ' + className;
	}
}


/**
 * removeClass
 * 
 * removes a css class from an element
 * 
 * @param el: DOM element: the element to remove the css class from
 * @param className: string: the class to remove
 * 
 */
function removeClass(el, className) {
	
	if (el.className === '') {
		return false;
	}
	else {
		
		var newCssClass = '';
		var classArray = el.className.split(' ');
		 
		for (var i = 0; i < classArray.length; i++) {
			
			if (classArray[i] !== className) {
				newCssClass += classArray[i] + ' ';
			}
		}
		
		// remove the final space
		newCssClass = newCssClass.substring(0, (newCssClass.length - 1));
		
		el.className = newCssClass;
	}
}


function checkForElement(id) {
	
	var el = document.getElementById(id);
	if (el) {
		return true;
	}
	
	return false;
}


// --------------- notify ScriptManager that script has loaded --------------------
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
