//
// DEFINITION
//


/**
 * Mainly a collection class
 * Manages all of the elements that can be used to modify dates
 */
var DateController = new Class({
	// Outlets -- elements that might need updating by this class
	outletDate: null,
	outletMonth: null,
	outletYear: null,
	outletDay: null,
	outletCalendar: null,
			
	initialize: function ( date, month, year, day, calendar ) {
		this.outletDate = date;
		this.outletMonth = month;
		this.outletYear = year;
		this.outletDay = day;
		this.outletCalendar = calendar;
	},
	
	/**
	 * Make sure the day of the month exists and that the user is not trying to reserve a date in the past
	 * Update the form to correct these issues if need be
	 */
	fixDay: function () {
		// Get the number of days in the month with a JS hack
		var arrival = new Date( this.outletYear.getValue(), this.outletMonth.getValue(), 0);
		var daysInMonth = arrival.getDate();
		
		if ( this.outletDate.getValue() > daysInMonth ) {
			this.outletDate.value = daysInMonth;
		}
		
		arrival = this.getDate();
		var now = new Date();
		
		if ( arrival < now ) {
			this.setDate( now );
		}
	},
	
	getDate: function () {
		var date = this.outletDate.getValue();
		var month = this.outletMonth.getValue();
		var year = this.outletYear.getValue();
		return new Date( year, month - 1, date )
	},
	
	setDate: function ( date ) {
		this.outletDate.value = date.getDate();
		this.outletMonth.value = date.getMonth() + 1;
		this.outletYear.value = date.getFullYear();
		this.outletDay.value = dayOfWeek[ date.getDay() ];
//		this.outletCalendar.reuild( this.outletCalendar );
	}
});


/**
 * Manages the entire reservation form
 */
var ResFormController = new Class({
	// Outlets -- elements that might need updating by this class
	outletArrive: null,
	outletDepart: null,
	outletNights: null,
	
	initialize: function ( arrive, depart, nights ) {
		this.outletArrive = arrive;
		this.outletDepart = depart;
		this.outletNights = nights;
	},
	
	// Actions -- aka event handlers
	actionChangeArrival: function ( event ) {
		this.outletArrive.fixDay();
		var arrivalDate = this.outletArrive.getDate();
		var departureDate = this.outletDepart.getDate();
		
		if ( arrivalDate >= departureDate ) {
			// Set departure date to one day after arrival date
			departureDate = new Date( arrivalDate );
			departureDate.setDate( departureDate.getDate() + 1 );
			this.outletDepart.setDate( departureDate );
		}
		this.updateDay( arrivalDate, departureDate );
		var days = Math.round( (departureDate - arrivalDate) / 86400000 ); // Milliseconds
		this.outletNights.value = days;
	},
	actionChangeDeparture: function ( event ) {
		this.outletDepart.fixDay();
		var arrivalDate = this.outletArrive.getDate();
		var departureDate = this.outletDepart.getDate();
		
		if ( arrivalDate >= departureDate ) {
			// Set arrival date to one day before departure date
			arrivalDate = new Date( departureDate );
			arrivalDate.setDate( arrivalDate.getDate() - 1 );
			this.outletArrive.setDate( arrivalDate );
		}
		this.updateDay( arrivalDate, departureDate );
		var days = Math.round( (departureDate - arrivalDate) / 86400000 );
		this.outletNights.value = days;
	},
	actionChangeNights: function ( event ) {
		var arrivalDate = this.outletArrive.getDate();
		var days = Number( this.outletNights.getValue() );
		if ( days > 0 ) {
			var departureDate = new Date( arrivalDate );
			departureDate.setDate( departureDate.getDate() + days );
			this.outletDepart.setDate( departureDate );
			this.actionChangeDeparture();
		}
	},
	
	updateDay: function ( arrival, departure ) {
		this.outletArrive.outletDay.value = dayOfWeek[ arrival.getDay() ];		 
		this.outletDepart.outletDay.value = dayOfWeek[ departure.getDay() ];
	}
});

/**
 * Allows only numbers to be entered
 * Use with the onkeydown event handler of an input field
 */
var numbersOnlyFilter = function( e ) {
	var e = new Event( e );
	if ( ( e.code > 47 && e.code < 58 ) || ( e.code > 95 && e.code < 106 ) || e.code == 8 ) {
	} else {
		// User did not enter a number
		e.stop();
	}
}

var dayOfWeek = new Array( 7 );
dayOfWeek[ 0 ] = "Sunday";
dayOfWeek[ 1 ] = "Monday";
dayOfWeek[ 2 ] = "Tuesday";
dayOfWeek[ 3 ] = "Wednesday";
dayOfWeek[ 4 ] = "Thursday";
dayOfWeek[ 5 ] = "Friday";
dayOfWeek[ 6 ] = "Saturday";


//
// IMPLEMENTATION
//

window.addEvent( 'domready', function() {
	var nodeResForm = $( 'resform' );
	
	// Grab all of the nodes that we'll be working with
	// This is kind of resource intensive, so we should only do this once
	var nodeArriveDate = nodeResForm.getElement( 'select[name=arriveDate]' );
	var nodeArriveMonth = nodeResForm.getElement( 'select[name=arriveMonth]' );
	var nodeArriveYear = nodeResForm.getElement( 'select[name=arriveYear]' );
	var nodeArriveDay = nodeResForm.getElement( 'input[name=arriveDay]' );
	var nodeArriveCalendar = new Calendar({ arriveDay: {arriveDate: 'j', arriveMonth: 'n', arriveYear: 'Y', arriveDay: 'l' }}, 
										{ direction: 0.5 }); // uses calendar.*.js
	
	var nodeDepartDate = nodeResForm.getElement( 'select[name=departDate]' );
	var nodeDepartMonth = nodeResForm.getElement( 'select[name=departMonth]' );
	var nodeDepartYear = nodeResForm.getElement( 'select[name=departYear]' );
	var nodeDepartDay = nodeResForm.getElement( 'input[name=departDay]' );
	var nodeDepartCalendar = new Calendar({ departDay: {departDate: 'j', departMonth: 'n', departYear: 'Y', departDay: 'l' }}, 
										{ direction: 1 }); // uses calendar.*.js

	var nodeNights = nodeResForm.getElement( 'input[name=numberOfNights]' );
	
	// Instantiate the form controllers and set the outlets
	var arriveDateController = new DateController( nodeArriveDate, 
										nodeArriveMonth,
										nodeArriveYear,
										nodeArriveDay,
										nodeArriveCalendar );
										
	var departDateController = new DateController( nodeDepartDate, 
										nodeDepartMonth,
										nodeDepartYear,
										nodeDepartDay,
										nodeDepartCalendar );
										
	var resFormController = new ResFormController( arriveDateController, 
												departDateController, 
												nodeNights );
												
	// Set the Arrival fields to today and the Departure fields to tomorrow
	var now = new Date();
	arriveDateController.setDate( now );

	var tomorrow = new Date( now.setDate( now.getDate() + 1 ) );
	departDateController.setDate( tomorrow );
	
	resFormController.outletArrive.outletCalendar.options.onchange = resFormController.actionChangeArrival.bind( resFormController );
	resFormController.outletDepart.outletCalendar.options.onchange = resFormController.actionChangeDeparture.bind( resFormController );
		
		
	// Set the actions so the form updates itself when a user changes something
	nodeArriveDate.addEvent( 'change', resFormController.actionChangeArrival.bindWithEvent( resFormController ) );
	nodeArriveMonth.addEvent( 'change', resFormController.actionChangeArrival.bindWithEvent( resFormController ));
	nodeArriveYear.addEvent( 'change', resFormController.actionChangeArrival.bindWithEvent( resFormController ) );
	
	nodeDepartDate.addEvent( 'change', resFormController.actionChangeDeparture.bindWithEvent( resFormController ) );
	nodeDepartMonth.addEvent( 'change', resFormController.actionChangeDeparture.bindWithEvent( resFormController ));
	nodeDepartYear.addEvent( 'change', resFormController.actionChangeDeparture.bindWithEvent( resFormController ) );
	
	nodeNights.addEvent( 'keyup', resFormController.actionChangeNights.bindWithEvent( resFormController ) );
	
	// Prevent users from entering anything besides numbers and control characters
	// Remove this if it doesn't work on non-US keyboards
	nodeNights.addEvent( 'keydown', numbersOnlyFilter );
	nodeResForm.getElement( 'input[name=rooms]' ).addEvent( 'keydown', numbersOnlyFilter );
});