//  Minimum exit offset, comparing serialised date-times (e.g. entry "200905010300", exit "200905010400")
// Months and days are one based, i.e. the above examples are for 1st of May 2009

var minExitOffset = 100;  // If you change this, also change the relevant error message!

//  Set as global, for later setting and reference
var minEntryDateTime = "";

// debug boolean. if set set to true, messages are logged to the console log
var debug = false;

// How many days do months have? Note: zero-based!
// Have included 3 letter month code for debugging purposes
var daysInMonth = [
        [31, "Jan"],
        [28, "Feb"],
        [31, "Mar"],
        [30, "Apr"],
        [31, "May"],
        [30, "Jun"],
        [31, "Jul"],
        [31, "Aug"],
        [30, "Sep"],
        [31, "Oct"],
        [30, "Nov"],
        [31, "Dec"]
    ];
	
var errors = new Array();
	
/**
 * Takes string created by dropdownDateTime ("CCYYMMDDHHmm")
 * and works out whether this date is valid (i.e. exists).
 * Returns true if valid, false if not.
 *
 */
function checkValidDate(dateStr) {
    // extract year, month and date from date string
    var dateYear = parseInt(dateStr.substr(0,4),10);
    var dateMonth = parseInt(dateStr.substr(4,2),10);
    var dateDay = parseInt(dateStr.substr(6,2),10);
    
    if (debug) { console.log("year, month, day = " + dateYear + ' | ' + dateMonth + ' | ' + dateDay); }
    
    // Adjust daysInMonth array for leap years. This needs to be calculated 
    // every time the date is checked to be valid, as it's only really relevant (and 
    //    correct!) if the date that is being checked is in February
    if ( dateYear % 4 == 0 ) {
        daysInMonth[1][0] = 29;
        if ( dateYear % 100 == 0 && dateYear % 400 != 0 ) {
            daysInMonth[1][0] = 28;
        }
    }
    
    // What is the last day of the month being checked
    var lastDay = daysInMonth[(dateMonth - 1)][0];
    
    if (debug) { console.log("last day for month " + lastDay); }
    
    // is the day in dateStr earlier or the same as last valid day
    if ( dateDay <= lastDay ) {
        if (debug) { console.log("Date is valid"); }
        return true;
    }
    else {
        if (debug) { console.log("Date is NOT valid"); }
        return false;
    }
}

/**
 *  Dropdown Date-Time
 *  Takes day, month-year and time obj refs and then concatenates their
 *  values into a simple "CCYYMMDDHHmm" string.
 *  Last modified: 2009-05-29 {pf}
 */
function dropdownDateTime(dropdownDay, dropdownMonthYear, dropdownTime) {
    
    var dropdownMonth = dropdownMonthYear.substring(0,2);
    var dropdownYear = dropdownMonthYear.substring(2);
    var dropdownTimeArr = dropdownTime.split(':');
    
    var dropdownDateTime = dropdownYear + dropdownMonth + dropdownDay + dropdownTimeArr[0] + dropdownTimeArr[1];
    
    return dropdownDateTime;
}

/**
 *  Takes 2 strings as produced by the dropdownDateTime function,
 *  extracts the dates and compares them.
 * 	If the strings are identical, returns true, false if not identical.
 */
function compareDates( dateTime1, dateTime2 ) {
	var date1 = dateTime1.substr(0,8);
	var date2 = dateTime2.substr(0,8);
	if ( date1 == date2 ) {
		return true;
	} 
	else {
		return false;
	}
}

/**
 *  calculate day before
 *  Takes a date in string format "CCYYMMDDHHmm"
 *  and returns the day before.
 */
function calculateDayBefore( tomorrow ) {
	if (debug) { console.log("calculated tomorrow string: " + tomorrow); }
	
	var year = tomorrow.substr(0,4);
	// months are one based in the string notation, zero based for the Date object
	var month = parseInt(tomorrow.substr(4,2),10) - 1;
	// correct for negative months after subtracting 1
	if(month < 0) {month += 12 };
	var day = tomorrow.substr(6,2);
	
	if (debug) { console.log("calculated today date: " + day + ' / ' + month + ' / ' + year); }
	
	var tomorrowDte = new Date( year, month, day );
	
	// subtract one day's worth of milliseconds from tomorrow
	var todayInMilliSeconds = tomorrowDte.getTime() - (24*60*60*1000);
	
	if (debug) { console.log("calculated milliseconds: " + todayInMilliSeconds); } 
	
	var todayDte = new Date(todayInMilliSeconds);
	
	if (debug) { console.log("calculated today date: " + todayDte.toString()); } 
	
	// months need to go back to one-based notation
	var todayMonth = todayDte.getMonth() + 1;
	if ( todayMonth > 12 ) { todayMonth -= 12; }
	// add leading zero if necessary
	if ( todayMonth.toString().length == 1 ) { todayMonth = "0" + todayMonth; }
	
	// days need a leading zero
	var todayDay = todayDte.getDate();
	if ( todayDay.toString().length == 1 ) { todayDay = "0" + todayDay; }
	
	var todayStr = '';
	todayStr += todayDte.getFullYear();
	todayStr += todayMonth;
	todayStr += todayDay;
	todayStr += tomorrow.substr(8,4);
	
	return todayStr;
}


/**
 *  Compare Date-Times
 *  Compares one date-time string to another, returns the offset.
 *  Last modified: 2009-05-06 {pf}
 */
function compareDateTimes(lowerDateTime, upperDateTime) {
    
    var lowerInt = parseInt( lowerDateTime );
    var upperInt = parseInt( upperDateTime );
    var diffInt = (upperInt - lowerInt);
    
    return (diffInt);
    
}


/**
 *  Check Date-Times
 *  Compiles the two user-input date-times into integers and checks
 *  them against various mandatory conditions (min entry, min exit).
 *  Last modified: 2009-06-04 {id}
 */
function checkDateTimes() {
    
	var userEntryDateTime = dropdownDateTime( $(':input.carParkEntryDay').val(), $(':input.carParkEntryMonthYear').val(), $(':input.carParkEntryTime').val() );
    var userExitDateTime = dropdownDateTime( $(':input.carParkExitDay').val(), $(':input.carParkExitMonthYear').val(), $(':input.carParkExitTime').val() );
    var userDateTimeDiff = compareDateTimes(userEntryDateTime, userExitDateTime);
	
	var today = calculateDayBefore(minEntryDateTime);
	if (debug) { console.log("calculated today string: " + today); }
	
	// check entry date
	
	// Is it a valid date?
	if ( checkValidDate(userEntryDateTime) ) {
		// Is it before today?
		if ( userEntryDateTime < today ) {
			errors.push("Please select an entry date after today's date.");
		} 
		else {	
			// if entry date is today
			if ( userEntryDateTime < minEntryDateTime ) {
				errors.push("Bookings cannot be made for an arrival less than 3 hours from now. However, spaces are available on the day at the drive-up price.\n\nYou also cannot book for a time earlier than now.");
			}
		}		
	} 
	else {
		errors.push("Please enter a valid entry date.");
	}
	
	// check exit date
	
	// is an exit date selected?
	if ( $(':input.carParkExitDay').val() != '' && $(':input.carParkExitMonthYear').val() != '' ) {
		// is the exit date valid?
		if ( checkValidDate(userExitDateTime) ) {
			// Is it before today?
			if ( userExitDateTime < today ) {
				errors.push("Please select an exit date after today's date.");
			} 
			else {
				// is it an hour later than entry time?
				if ( userDateTimeDiff < minExitOffset ) {
					errors.push("Please select an exit date that is after the entry date.");
				}
			}
		} 
		else {
			errors.push("Please enter a valid exit date.");
		}
	}
	else {
		// no exit date selected
		errors.push("Please select the date when you wish to exit the car park.");
	}
	
	if ( $(':input.carParkExitTime').val() == '' ) {
		// no exit time selected
		errors.push("Please select the time when you wish to exit the car park.");
	}
	
	
	var len = errors.length;
	
	if (debug) { console.log("number of errors: " + len); }
	
	// if there are no errors, submit the form
	if( len == 0 ) {
		return true;
	} 
	else {
		// if there are errors, concatenate them & alert them 
		var errorStr = '';
		for ( var i = 0; i < len; i++ ) {
			errorStr += errors[i] + '\n\n';
		}
		alert(errorStr);
		
		// Clear out the array so the same errors don't keep being
		// shown even after you've corrected them.
		for ( var j = 0; j < len; j++ ) {
				errors.pop();
			}
		errorStr = '';
		
		// and stop form from submitting
		return false;
	}
}


/**
 *  Update Parking Entry Dropdowns
 *  Last modified: 2009-05-13 {pf}
 */
function updateEntryDate(argObj) {
    
    var monthYear = argObj.mm + argObj.yyyy; /* concatenates rather than adds (which is what we want) */
    
    //  Update dropdowns (always by class; fondest regards to .NET)
    $(':input.carParkEntryDay').val(argObj.dd);
    $(':input.carParkEntryMonthYear').val(monthYear);
    
};// semi-colon necessary for use in Date Picker "dateselect" callback


/**
 *  Update Parking Exit Dropdowns
 *  Last modified: 2009-05-13 {pf}
 */
function updateExitDate(argObj) {
    
    var monthYear = argObj.mm + argObj.yyyy;
    
    //  Update dropdowns (always by class; fondest regards to .NET)
    $(':input.carParkExitDay').val(argObj.dd);
    $(':input.carParkExitMonthYear').val(monthYear);
    
};// semi-colon necessary for use in Date Picker "dateselect" callback


/**
 *  Update Hidden Entry Date
 *  last modified: 2009-06-01 {pf}
 */
function updateHiddenEntryDate() {
    
    var entryMonth = $(':input.carParkEntryMonthYear').val().substring(0,2);
    var entryYear = $(':input.carParkEntryMonthYear').val().substring(2);
    var entryDate = $(':input.carParkEntryDay').val();
    
    $(':input.carParkEntryText').val(entryDate + '/' + entryMonth + '/' + entryYear);
    
}


/**
 *  Update Hidden Exit Date
 *  last modified: 2009-06-01 {pf}
 */
function updateHiddenExitDate() {
    
    var exitMonth = $(':input.carParkExitMonthYear').val().substring(0,2);
    var exitYear = $(':input.carParkExitMonthYear').val().substring(2);
    var exitDate = $(':input.carParkExitDay').val();
    
    $(':input.carParkExitText').val(exitDate + '/' + exitMonth + '/' + exitYear);
    
}


//  Bind onload [jQuery]
$(function() {
    
    if ( $(':input.carParkBookButton') ) {
        
        
        //  Get min date-time as set by server-side code in hidden input
        minEntryDateTime = $(':input.carParkMinEntry').val();
        
        
        //  Update hidden entry date on dropdown change
        $(':input.carParkEntryDay').change( function() {
            if ( $(this).val() > 0 ) {
                updateHiddenEntryDate();
            }
        });
        $(':input.carParkEntryMonthYear').change( function() {
            if ( $(this).val() > 0 ) {
                updateHiddenEntryDate();
            }
        });
        
        
        //  Update hidden exit date on dropdown change
        $(':input.carParkExitDay').change( function() {
            if ( $(this).val() > 0 ) {
                updateHiddenExitDate();
            }
        });
        $(':input.carParkExitMonthYear').change( function() {
            if ( $(this).val() > 0 ) {
                updateHiddenExitDate();
            }
        });
        
        
        //  Validate and then compare entry and exit date-times on attempted form submission
        $(':input.carParkBookButton').click( function() {
            return checkDateTimes();
        });
        
        
    }
    
});

