var totalTime = new TimeObj(0, 0);
var times = [];
var isIe = window.event ? true : false;

// Time Object.
// Constructor:
//  converts seconds over 60 to minutes + rest seconds;
//	converts minutes over 60 to hours + rest minutes;
// 	converts fractions of hours to minutes.
function TimeObj(h, m, s)
{
	this.h = h > 0 ? h : 0;
	this.m = m > 0 ? m : 0;
	this.s = s > 0 ? s : 0;

	// add seconds over 60 to minutes
	if ( this.s > 59 )
	{
		this.m += Math.floor(this.s / 60);
		this.s = this.s % 60;
	}	
		
	// add minutes over 60 to hours
	if ( this.m > 59 )
	{
		this.h += Math.floor(this.m / 60);
		this.m = this.m % 60;
	}
	
	this.getHours = function()
	{
		return this.h;
	}
	
	this.getMinutes = function()
	{
		return this.m;
	}
	
	this.getSeconds = function()
	{
		return this.s;
	}
	
	this.getFormattedTime = function(format)
	{
		// format as strings.
		// mins, secs: add heading 0 if under 10
		var hStr = this.h.toString();
		var mStr = this.m < 10 ? '0' + this.m.toString() : this.m.toString();
		var sStr = this.s < 10 ? '0' + this.s.toString() : this.s.toString();
		var ret;
		
		if( format == 'table' )
		// return as html table row (without <tr></tr>)
		{
			ret = "<td>" + hStr + ":</td>\n";
			ret += "\t<td>"+ mStr +":</td>\n";
			ret += "\t<td>"+ sStr +"</td>\n";
		}
		// hh:mm:ss am/pm
		else if ( format == 'clock' )
			// hours : minutes
		{
			if( this.h > 12 ) // pm time
			{
				ret = (this.h - 12).toString() + ':' + mStr + ':' + sStr + ' pm';
			}
			else if( this.h == 12 ) // 12pm
			{
				ret = (this.h).toString() + ':' + mStr + ':' + sStr + ' pm';
			}
			else
			{
				ret = hStr + ':' + mStr + ':' + sStr  + ' am';
			}
		}
		else
			// hh:mm:ss
		{
			ret = hStr + ':' + mStr + ':' + sStr;
		}
		return ret;
	}
	
	/* Compares this TimeObj to another TimeObj.
	 * Treats hours and minutes as time of day.
	 * Uses 24-hour time.
	 * This time has to be earlier than time compared to (that).
	 * @return false if non-valid times, otherwise new TimeObj:difference in hours, minutes.*/
	this.compareClockTimes = function(that)
	{
		if ( this.getHours() + (this.getMinutes() / 60) + (this.getSeconds() / 3600) >= 
		 	 that.getHours() + (that.getMinutes() / 60) + (that.getSeconds() / 3600))
		{
			alert("Start-time ("+this.getFormattedTime('clock')+") is either the same, or later than end-time ("+that.getFormattedTime('clock')+"). Please enter a start-time that is earlier than the end-time.");
			return false;
		}		

		// make copies so we don't modify original time objects
		a = new TimeObj(this.h, this.m, this.s);
		b = new TimeObj(that.h, that.m, that.s);
		
	 	// adjust minutes if toSeconds < fromSeconds
		if ( b.getSeconds() < a.getSeconds() )
		{
			a.m += 1;
			b.s += ( 60 - a.getSeconds() )
			a.s = 0;		
		}

		// adjust hours if toMinutes < fromMinutes
		if ( b.getMinutes() < a.getMinutes() )
		{
			a.h += 1;
			b.m += ( 60 - a.getMinutes() )
			a.m = 0;		
		}
		
		return new TimeObj(b.h - a.h, b.m - a.m, b.s - a.s)
	}
}

function calculate()
{  
	var fromStr = document.getElementById("fromTime").value;
	var toStr = document.getElementById("toTime").value;

	var fAM = document.getElementById("fromAM").selected;
	var fPM = document.getElementById("fromPM").selected;
	var tAM = document.getElementById("toAM").selected;
	var tPM = document.getElementById("toPM").selected;
	
	// both times must be entered
	if(fromStr.length == 0 || toStr.length == 0)
	{
		alert('Please enter both start-time and end-time.');
		return;
	}
	
	// split on . or : or hhmm or hmm
	from = fromStr.split(/:|\./g);
	to = toStr.split(/:|\./g);
	
	// check so we have numbers
	for(var i=0; i<from.length; i++)
	{
		if(isNaN(parseInt(from[i])))
		{
			alert(fromStr + ' is not a valid time. Please enter a time in the format hh:mm. Example: 1:34');
			return;
		}
	}
	for(var i=0; i<to.length; i++)
	{
		if(isNaN(parseInt(to[i])))
		{
			alert(fromStr + ' is not a valid time. Please enter a time in the format hh:mm. Example: 1:34');
			return;
		}
	}
	
	var fH, fM, fS, tH, tM, tS;
	fH = fM = fS = tH = tM = tS = 0;

	// PARSE FROM-TIME
	// Convert to Integers
	if ( from.length == 1  && !isNaN( parseInt( fromStr ) ) )
	{
		fH = parseInt( fromStr, 10 );
	}
	else if ( from.length >= 2 )
	{	// parse hours and minutes
		fH = parseInt( from[0], 10 );
		fM = parseInt( from[1], 10 );
	}
	else
	{
		alert("Please enter start-time in this format: 'hh:mm' or 'hh.mm'. Example: '1:34'. Seconds are optional ('hh:mm:ss')");
		return;
	}
	// were seconds specified?
	if ( from.length == 3 )
	{
		fS = parseInt( from[2], 10 );
	}
		
	
	// PARSE TO-TIME
	// Convert to Integers
	if ( to.length == 1 && !isNaN( parseInt( toStr ) ) )
	{
		tH = parseInt( toStr, 10 );
	}	
	else if ( to.length >= 2 )
	{
		tH = parseInt( to[0], 10 );
		tM = parseInt( to[1], 10 );
	}
	else
	{
		alert("Please enter end-time in this format: 'hh:mm' or 'hh.mm'. Example: '1:34'. Seconds are optional ('hh:mm:ss')");
		return;
	}
	// were seconds specified?
	if ( to.length == 3 )
	{
		tS = parseInt( to[2], 10 );
	}
	// make sure times to compare are valid 24-hour times of day
	if ( 	(fH > 12 || tH > 12) ||
			(fM > 59 || tM > 59) ||
			(fS > 59 || tS > 59) )
	{
		alert("Please enter a valid 12-hour clock time. Hours can be 0-12, minutes and seconds can be 0-59. Valid time format is hh:mm:ss");
		return;
	}
	
	// check for special case of 00:xx pm
	if ( 	(fPM && fH == 0) ||
			(tPM && tH == 0) )
	{
		alert("PM (afternoon) hours must be 1-12. A time like '0:45pm' doesn't exist.");
		return;
	}

	// Add 12 to PM hours

	// From-time
	if ( fPM && fH != 12)
		fH += 12;
	else if ( fAM && fH == 12 )
		fH = 0;

	// To-time
	if ( tPM && tH != 12)
		tH += 12;
	else if ( tAM && tH == 12 )
		tH = 0;

	// Everything OK!
	
	from = new TimeObj(fH, fM, fS);
	to = new TimeObj(tH, tM, tS);
	
	var diff = from.compareClockTimes( to );
	if(!diff)
	{
		// something went wrong comparing.
		// error message was displayed.
		// fail silently.
		return;
	}
		
	// push onto stack
	times.push([from, to, diff]);
	
	// add to total
	totalTime = new TimeObj(
		totalTime.getHours() + diff.getHours(),
		totalTime.getMinutes() + diff.getMinutes(),
		totalTime.getSeconds() + diff.getSeconds()
	);	

	var x = document.getElementById("results");
	var results = "<table><tr><th>From</th><th></th><th>To</th><th class='right'>H</th><th class='right'>m</th><th class='right'>s</th></tr>";

	for(var i = 0; i < times.length; i++)
	{
		// display fromTime, toTime, and the difference in h:m:s
		results += '<tr><td>' + times[i][0].getFormattedTime('clock') + '<td>&nbsp;&nbsp;&#8212;&nbsp;&nbsp;</td></td><td>' +
		 			times[i][1].getFormattedTime('clock') + '</td>' +
		 			times[i][2].getFormattedTime('table') + "</tr>\n";
	}
	
	results += "<th></th><th></th><th></th><th>Total Time</th>"
	results += '<tr class="total"><th></th><th></th><th></th>' +
	 			totalTime.getFormattedTime('table') + "</tr></table>\n";

	x.innerHTML = results;
	x.style.display = "block";
}

$(document).ready(function()
{
	// attach return key listener to input elements
	$('input').bind('keydown', function(e){
		e = e || window.event;

		if(e.type=='keydown' || e.type=='onkeydown')
		{
			var code = isIe ? e.keyCode : e.which;
		 	if ( code != 13 )
				return;
			else
				calculate();
		}
		
	});
});
