// Functions to add or remove days from a date.
Date.prototype.addDays = function(days) {
	this.setDate(this.getDate()+Number(days));
}

Date.prototype.removeDays = function(days) {
	this.setDate(this.getDate()-Number(days));
}

// Mapping of all Florida locations to IDs
floridaLocations = {};

floridaLocations['127910'] = 'Florida';
	floridaLocations['128028'] = 'Orlando';
		floridaLocations['128222'] = 'Kissimmee';
		floridaLocations['128223'] = 'Lake Buena Vista';
		floridaLocations['128224'] = 'Universal Orlando Resort';
		floridaLocations['128225'] = 'Walt Disney World Resort';
		floridaLocations['128221'] = 'International Drive';
	floridaLocations['131830'] = 'Gulf Coast';
		floridaLocations['131854'] = 'Bradenton';
		floridaLocations['131835'] = 'Clearwater';
		floridaLocations['131841'] = 'Fort Myers';
		floridaLocations['131847'] = 'Indian Rocks';
		floridaLocations['131852'] = 'Sarasota';
		floridaLocations['131839'] = 'St Pete Beach';
		floridaLocations['131850'] = 'Treasure Island';
		floridaLocations['136997'] = 'New Port Richey';

// Calendar object that stores all the relevant values of of the calendar
CalendarInfo = function () {
			// Start date is initially read from the form (gets default or session date)
 			this.startDate = jQuery("#dateRange\\.startDate").val();
 			this.endDate = null;
			// Duration is initially read from the form (gets default or session duartion)
 			this.duration = jQuery("#dateRange\\.duration").val();
			// View dates are the human readable dates e.g. Fri 23 Feb 2009
 			this.startViewDate = null;
 			this.endViewDate = null;
 		};
 		
CalendarInfo.prototype = {
			
			// Converts a date object into a human readable date e.g. Fri 23 Feb 2009
 			dateToViewDate: function ( date )  {
 					return jQuery.datepicker.formatDate('D dd M yy', date );
 			},
 			
			// Converts a date object into a slash-delimeted date e.g. 23/02/2009
 			dateToString : function ( date ) {
 				return jQuery.datepicker.formatDate('dd/mm/yy', date);
 			},
 			
			// Returns true if selectedDate is between the start and end dates
 			isDateValid : function ( selectedDate ) {
 			 		return (selectedDate >= this.startDate && selectedDate <= this.endDate);
 			},
 			
			// Converts a slash-delimeted date, e.g. 23/02/2009 into a date object
 			stringToDate : function( dateString ) {
 				return jQuery.datepicker.parseDate( 'dd/mm/yy', dateString ) 
 			},
 			
			// Creates a new CalendarInfo object, converts startDate into a date object
			// Calculates and updates all remaining values
 			createCalendarInfo : function() {
 					var calendarInfo = new CalendarInfo( );
 					this.startDate = this.stringToDate( this.startDate );
 					this.updateAll( );
  					return calendarInfo;
 			},
 			
			// Creates and end date from the start date and duration
 			updateAll : function ( ) {
				this.startViewDate = this.dateToViewDate( this.startDate );
				this.endDate = new Date( this.startDate );
				this.endDate.addDays( this.duration );
				this.endViewDate = this.dateToViewDate( this.endDate );
 			}
}

// Calendar manager object
CalendarManager = function () {
 		this.startCalendar = null;
 		this.endCalendar = null;
 		this.calendarInfo = null;
		this.isInitiated = false;

 		this.init();
};

CalendarManager.prototype = {
 		
		// Create a new calendar object and from this build the two calendars showing start and end dates
		init : function () {
			this.calendarInfo = new CalendarInfo();
			this.calendarinfo = this.calendarInfo.createCalendarInfo();
			this.createCalendar('dateFrom');
			this.createCalendar('dateTo');
			this.copyToForm('dateFrom');
			this.isInitiated = true;
		},
		
		// Highlights all dates that are valid (between the start and end dates)
		highlight : function(date){
			var highlightClass = ( this.calendarInfo.isDateValid( date ) ) ? "selected":"";		 	
	  		return [true,highlightClass];
		},
		
		// Create a calendar using jquery datepicker using the supplied divId as its container		
		createCalendar : function ( divId ) {
				
				var self = this;
				var startOrEnd = ( divId == "dateFrom" )? "startDate" : "endDate";
				// number of days ahead of today to be the first valid day; 0 = today
				var minDays = ( divId == "dateFrom" )? "0" : Number(this.calendarInfo.duration);

				jQuery("#"+divId).datepicker( {
					  // When building the calendar what preprocessing should be done on each day before building it
			 		  beforeShowDay: function( date ) {
							// apply a selected class to all days that are between the start and end dates
			 		  		var highlightClass = ( self.calendarInfo.isDateValid( date ) ) ? "selected":"";		 	
			 		  		return [true,highlightClass];	 		  
			 		  },
					  // altField is the input field to store the selected dates in its respective format
					  altField: '#dateRange\\.'+startOrEnd,
					  altFormat: 'dd/mm/yy',
					  dateFormat:'dd/mm/yy',
					  // Allow the user to change the month and year of the calendar
					  changeMonth: true,
					  changeYear: true,
					  minDate: +Number(minDays),
					  yearRange:"-2:+2",
					  // Default date to use comes from calendarInfo object which comes from the session or portlet defaults
					  defaultDate: self.calendarInfo[startOrEnd], 
					  showOtherMonths: true,
					  dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
					  monthNamesShort: ['January','February','March','April','May','June','July','August','September','October','November','December'],
					  // First day of the week is Sun by default. 1 is Mon, 2 is Tue etc...
					  firstDay: 1,
					  // Callback function for clicking on a date
					  onSelect: function(dateText, inst) {
								// Update the calendarInfo object with the new dates
								self.calendarInfo[startOrEnd] = new Date( self.calendarInfo.stringToDate(jQuery("#dateRange\\."+startOrEnd).val()) );
								if(divId == 'dateTo') {
									var temp = new Date(self.calendarInfo.endDate);
									temp.removeDays(self.calendarInfo.duration);
									self.calendarInfo.startDate = temp;
									jQuery('#dateRange\\.startDate').val(self.calendarInfo.dateToString( temp ));
								}
								self.calendarInfo.updateAll();
								self.copyToForm( divId );
			  		 },
				  	 // Callback for when the user changes a month or year
					 // N.B Datepicker runs this callback when the calendar is initialised
					 onChangeMonthYear: function(year, month, inst) {
						// Set the new months/years day to whatever day was selected from the previous month/year
						var day = inst.currentDay;
						// Prevents this callback from doing anything until it the calendars have been initialised
						if(self.isInitiated) {
							jQuery('#'+divId).datepicker( 'setDate',new Date(month+"/"+day+"/"+year) );
							jQuery('#'+divId).find('td.ui-datepicker-current-day').trigger("click");
						}
					 }			  
				 });
			},
			
			// Copies values from CalendarInfo object into form inputs
			copyToForm : function( calendarDiv ) {
 				if(calendarDiv == 'dateTo') {
					jQuery('#dateFrom').datepicker('setDate',this.calendarInfo.startDate);
				} else if(calendarDiv == 'dateFrom'){
					jQuery('#dateTo').datepicker('setDate',this.calendarInfo.endDate);
				} else {
					jQuery('#dateFrom').datepicker('setDate',this.calendarInfo.startDate);
					jQuery('#dateTo').datepicker('setDate',this.calendarInfo.endDate);
				}
				jQuery('#dateRange\\.startDate').val(this.calendarInfo.dateToString(this.calendarInfo.startDate));
 				jQuery('#dateRange\\.endDate').val(this.calendarInfo.dateToString(this.calendarInfo.endDate));
 				jQuery('#dateRange\\.duration').val(this.calendarInfo.duration);
				jQuery('#triplength').val(this.calendarInfo.duration);
				if(jQuery("#viewDate").length > 0)
 					jQuery('#viewDate').val(this.calendarInfo.startViewDate);
 				jQuery('#departText').text("Depart: " + this.calendarInfo.startViewDate);
 				jQuery('#returnText').text("Return: " + this.calendarInfo.endViewDate);
 			},
			
			// Restricts Florida to only allow 14 nights - not virginholidays or option4 (TCD ONLY)
			limitDuration : function () {
				if( location.href.indexOf('virginholidays') + location.href.indexOf('opt4') < 0) { 
					this.removeAllOptions(document.getElementById('triplength'));

					// Alt search view can take in a location as a parameter and store it in a hidden field, hence the second check
					if(jQuery("#selectedLocations0 :selected:not(:contains('Florida'))").text() || (document.getElementById('selectedLocations0').type == 'hidden' && floridaLocations[document.getElementById('selectedLocations0').value] == undefined))
						this.addOption(document.getElementById('triplength'),'7 nights','7');

					this.addOption(document.getElementById('triplength'),'14 nights','14');
					this.changeDuration('14');
				}
			},
			
			// Adds new options to a select box
			addOption : function ( selectbox, text, value ) {
				var optn = document.createElement("option");
				optn.text = text;
				optn.value = value;
				selectbox.options.add(optn);
			},
			
			// Removes all options from a select box
			removeAllOptions : function ( selectbox ) {
				var i;
				for( i=selectbox.options.length-1; i>=0; i-- ) {
					selectbox.remove(i);
				}
			},
 			
			// Changes the duration of a holiday and updates the form and calendarinfo object
 			changeDuration : function ( days ) {
 				this.calendarInfo.duration = days;
 				this.calendarInfo.updateAll();
 				this.copyToForm( 'both' );
 			}
}

// calendarManagers variable placeholder for sanity checking.
var calendarManager = null;