/**
 * code inspired from http://bk.mitm.cz/wiki/blog/entries/2009_05_05_script_onload_handling
 */
function addScript(src, callbacks) {
    var script = document.createElement("script");
    script.type = "text/javascript";

    if (script.addEventListener) {
        script.addEventListener("load", callbacks.load, false);
        script.addEventListener("error", callbacks.error, false);
    } else {
        script.attachEvent("onreadystatechange", function() {
            if (script.readyState == 'loaded' || script.readyState == 'complete') {
            	callbacks.load(script.readyState);
            }
            /* FIXME: MSIE: should be some other state for 404/503 */
        });
    }

    try {
        script.src = src;
        document.getElementsByTagName("head")[0].appendChild(script);
    } catch (e) {
    	callbacks.error(e);
    }
}

jQuery.fn.dlSearchResults = function(options) {
	
	var init = function(node, options) {

		var test = false;
		var maxWait = 14;
		var expectedWait = 10;
		var resultJson, resultEle, progress, progressbar;
		
		var url = dl.searchJsonUrl;
		
		var joiner = "?";
		var addParam = function(name,value) {
			url += joiner + name + (value == null ? "" : "=" + encodeURIComponent(value));
			joiner = "&";
		}
		
		addParam('countryCode', options.countryCode);
		addParam('pickupLocation', options.pickupLocation);
		addParam('dropoffLocation', options.dropoffLocation);
		addParam('pickupDate', options.pickupDate);
		addParam('dropoffDate', options.dropoffDate);
		addParam('maxWait', maxWait);
		addParam('_', new Date().getTime());

		var uniqueCallbackName = "callback_" + new Date().getTime();
		addParam('callback', uniqueCallbackName);

		var showErrorCommunicatingWithServer = true;
		
		var queueError = function(message) {
			showErrorCommunicatingWithServer = false;
			resultJson = {type:"error", data:{message:message}};
		}
			
		var jsonTimeout = function() {
			queueError("Sorry, No response has been received from the server.  Please try again later.");
			processQueue();
		}
		var removeTimeout = function() {
			clearTimeout(timeoutRef);	
		}
		var jsonCallback = function(jsonResult) {
			showErrorCommunicatingWithServer = false;
			resultJson = jsonResult;
		}
		window[uniqueCallbackName] = jsonCallback;

		if (test) {
			jQuery.getJSON('/wp-content/plugins/drivelater/test-quotes.php?callback=?', function(data, textStatus) {
				jsonCallback('quotes', data);
			});
		}
		else {
			addScript(url, {
				load : function() {
					//IE may end up here, so we need to determine if the quotes have been returned, and if so this is a valid state, otherwise an error has occured
					if (showErrorCommunicatingWithServer) {
						queueError('Unable to communicate with server');
					}
					processQueue();
				},
				error : function() {
					queueError('Unable to communicate with server');
					processQueue();
				}
			});
		}
		
		// track view with analytics
		if (window.pageTracker) pageTracker._trackPageview('/click/search/' + options.pickupLocation);
		
		var timeoutRef = setTimeout(jsonTimeout, (maxWait * 1000) + 2000); // must be more than the server side timeout of waxWait seconds

		var expectedTime = expectedWait * 1000;
		var start = new Date().getTime();
		var end = start + expectedTime;
		setInterval(function() {
			if (progressbar) {
				var x = (1 - (end - new Date().getTime()) / expectedTime) * 100;
				progressbar.progressbar('value', x)
			}
		}, 500);
		
		var processQueue = function() {
			
			if (!(resultEle && resultJson)) return;
			
			progress.hide();
			
			if (resultJson.type == "error") {
				resultEle.html("Error: " + resultJson.data.message)
			}
			else if (resultJson.type == 'quotes') {
				var quotes = resultJson.data;
				if (quotes && quotes.length > 0) {
					
					var t = "";
					t += "<table cellpadding='4' cellspacing='0' width='100%' class='resultsTable tablesorter'>";
					t += "<thead><tr>" +
							"<th>Supplier</th>" +
							"<th>Size</th>" +
							"<th>Vehicle</th>" +
							"<th>Price</th>" +
							"<th>&nbsp;</th>" +
							"</tr></thead>";
					t += "<tbody>";
					
					jQuery.each(quotes,function(i, quote){

							quote.supplierCode = quote.supplierCode || '';
						
							var supplier = dl.suppliers[quote.supplierCode] || dl.suppliers[quote.supplierCode + '-au'] || dl.suppliers[quote.supplierCode.toLowerCase() + "-au"];
							
							if (supplier) {

								t += "<tr class='" + ((i%2==0) ? 'odd':'even') + "'>";
								
								t += "<td align='center' sortValue='" + supplier.name + "'>";
								t += "<img src='" + supplier.button + "' title='" + supplier.name + "'>";
								t += "</td>";
	
								t += "<td align='center'>";
								t += "<span class='vehicleType'>" + quote.vehicleType + "</span>";
								t += "</td>";
								
								/*
								t += "<td align='center'>";
								if (quote.vehicleImage) {
									t += "<img height='20' src='" + quote.vehicleImage + "'>";
								}
								else {
									t += "&nbsp;";
								}
								t += "</td>";
								*/
								
								var bookUrl = quote.bookUrl;
								var bookA = "<a target='_blank' href='" + bookUrl + "'>";
								var vehicle = "<span class='vehicleName'>" + quote.vehicleName + "</span>";
								var vehicleSortValue = quote.vehicleName + " " + (quote.vehicleDescription || '');
								if (quote.vehicleDescription) {
									vehicle += " <span class='vehicleDescription'>" + quote.vehicleDescription + "</span>";
								}
								if (quote.status != 'not-available') {
									vehicle = bookA + vehicle + "</a>";
								}
								t += "<td style='text-align:left;' sortValue='" + vehicleSortValue + "'>" + vehicle + "</td>";
	
								var priceHtml = "";							
								var priceSortValue = Number.MAX_VALUE;							
								if (quote.status == 'available') {
									priceHtml = "<span class='vehiclePrice'>$" + quote.price + "</span>";
									priceSortValue = quote.price;
								}
								else if (quote.status == 'not-available') {
									priceHtml += "<span class='vehicleNotAvailablestyle'>n/a</span>";
								}
								else {
									priceHtml += "<span class='vehicleNoResponse'>no response</span>";
								}
								
								t += "<td align='right' sortValue='" + priceSortValue + "'>" + priceHtml + "</td>";
								
								t += "<td align='right'>";
								if (quote.status == 'not-available') {
									t += "&nbsp;";
								}
								else {
									t += bookA + "Book</a>"
								}
									
								t += "</td>";
								
								t += "</tr>";
							}
					});
					t += "</tbody>";
					t += "</table>";
					resultEle.html(t);
					jQuery('.resultsTable', resultEle).tablesorter( {
						textExtraction: function(node){
							return node.getAttribute('sortValue') || node.innerHTML;
						},
						headers : {
				           4: { sorter: false }
						},
						sortList : [[3,0]]
					});
				}
				else {
					resultEle.html("No Vehicles are Available");
				}
			}
			else {
				resultEle.html("Unknown Response");
			}

			
			removeTimeout();
			delete window[uniqueCallbackName];
		}

		jQuery(node).slideUp("normal", function() {
			
			var resultsPage = jQuery("<div class='resultsPage'><h2>Search Results</h2><div class='progress'>Loading Rates Directly from Suppliers<div class='progressbar'></div></div><div class='results'></div></div>");
			progress = jQuery('.progress', resultsPage);
			progressbar = jQuery('.progressbar', resultsPage).progressbar();
			jQuery(node).empty().append(resultsPage).slideDown("normal", function() {
				resultEle = jQuery('.results', resultsPage);
				processQueue();
			});
			
		});

	}

	return this.each(function(){
		init(this, options)
	});
	
};

jQuery.fn.dlSearchForm = function() {

	var init = function(node, options) {

		var id = ('drivenow' + Math.random() + Math.random()).replace(/\./g,'');

		var monthNames=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
		var edited = {};
		var selectStartTag = function(id, style) {
			return "<select class='select' id='"+id+"' style=\"" + style + "\">";
		}
		var pad = function(s) {
			return (s<10?"0"+s:""+s);
		}
		var formatTimeValue = function(d) {
			return pad(d.getHours())+":"+pad(d.getMinutes())
		}
		var formatTimeDisplay = function(d) {
			var h = d.getHours(), m = d.getMinutes();
			return ""+(h==0?12:h>12?h-12:h)+":"+pad(m)+" "+(h<12?"AM":"PM");
		}
		var formatMonthYearValue = function(d) {
			return ""+d.getFullYear()+"-"+pad(d.getMonth()+1)
		}
		var dateTimeSelect = function(namePrefix) {
			var now = new Date();
			var h=selectStartTag(namePrefix+'DateTime.day', "width:60px;");
			for (var i = 1; i <= 31; i++) {
				h+="<option value='"+i+"'>"+i+"</option>";
			}
			h+="</select>";
			h+=selectStartTag(namePrefix+'DateTime.yearMonth', "width:100px;");
			var d = new Date(now.getFullYear(),now.getMonth(),1,0,0,0);
			for (var i = 0; i < 12; i++) {
				h+="<option value='"+formatMonthYearValue(d)+"'>"+monthNames[d.getMonth()]+" " +d.getFullYear()+"</option>";
				d.setMonth(d.getMonth()+1);
			}
			h+="</select>";
			h+=selectStartTag(namePrefix+'DateTime.hourMinute', "width:100px;");
			d = new Date(now.getFullYear(),now.getMonth(),1,0,0,0);
			for (var i = 0; i < 48; i++) {
				h+="<option value='"+formatTimeValue(d)+"'>"+formatTimeDisplay(d)+"</option>";
				d.setMinutes(d.getMinutes()+30);
			}
			h+="</select>";
			return h
		}
		var locationSelect = function(prefix) {
			var h=selectStartTag(prefix+'Location', "width:200px;");
			for (var i = 0; i < dl.locations.length; i=i+2) {
				h+="<option value='"+dl.locations[i]+"'>"+dl.locations[i+1]+"</option>";
			}
			h+="</select>";
			return h;
		}
		var getValue = function(name) {
			return getElement(name).value
		}
		var getElement = function(name) {
			return document.getElementById(id+name);
		}
		var setEdited = function(name) {
			edited[name]=true
		}
		var syncDropoffLocation = function() {
			if (!edited['dropoffLocation']) {
				getElement('dropoffLocation').selectedIndex = getElement('pickupLocation').selectedIndex 
			}
		}
		var syncDropoffDateTime = function() {
			if (!edited['dropoffDateTime']) {	
				var d = getDate('pickup');
				if (d) {
					d.setDate(d.getDate() + 1);
					setDate('dropoff', d);
				}
			}
		}
		var getDateUrl = function(name) {
			return getValue(name+'DateTime.yearMonth')+'-'+getValue(name+'DateTime.day')+'T'+getValue(name+'DateTime.hourMinute') + ":00";
		}
		var getDate = function(name) {
			var s = getValue(name+'DateTime.yearMonth').replace("-", ",")+','+getValue(name+'DateTime.day')+','+getValue(name+'DateTime.hourMinute').replace(":", ",");
			var p = s.split(',')
			var month = Number(p[1])-1;
			var d = new Date(p[0], month, p[2], p[3], p[4], 0)
			return (d.getMonth() == month && d.getDate() == p[2]) ? d : null;
		}
		var setDate = function(name, date) {
			if (date) {
				getElement(name+'DateTime.yearMonth').value = formatMonthYearValue(date)  
				getElement(name+'DateTime.day').value = ""+date.getDate()
				getElement(name+'DateTime.hourMinute').value = formatTimeValue(date)
			}	
		}
		var validate = function() {
			var now = new Date()
			var pickupLocation = getValue('pickupLocation')
			if (!pickupLocation) { 
				alert('Please choose a Pick-up Location');
				return false;
			}
			var dropoffLocation = getValue('dropoffLocation')
			if (!dropoffLocation) { 
				alert('Please choose a Drop-off Location');
				return false;
			}
			var pickupDate = getDate('pickup')
			if (!pickupDate) {
				alert('Please choose a Pick-up Date');
				return false;
			}
			var dropoffDate = getDate('dropoff')
			if (!dropoffDate) {
				alert('Please choose a Drop-off Date');
				return false;
			}
			if (dropoffDate.getTime() <= pickupDate.getTime()) {
				alert('Please choose a Drop-off Date that is after the Pick-up Date');
				return false;
			}
			return true;
		}
		var selectLocation = function(location) {
			getElement('pickupLocation').value = location;
			getElement('pickupLocation').onchange();
		}
		
		var h = "";
		h += "<div class='panel'>"; 
		h += "  <table width='340' border='0' cellpadding='0' cellspacing='0' height='120' style='padding-left:10px'>";
		h += "		<tr class='pickupOrDropoff pickup'>";
		h += "			<td>Pick-up</td>";
		h += "			<td>" + locationSelect(id+'pickup') + "</td>";
		h += "		</tr>";
		h += "		<tr>";
		h += "			<td>&nbsp;</td>";
		h += "			<td>" + dateTimeSelect(id+'pickup') + "</td>";
		h += "		</tr>";
		h += "		<tr class='pickupOrDropoff dropoff'>";
		h += "			<td>Drop-off</td>";
		h += "			<td>" + locationSelect(id+'dropoff') + "</td>";
		h += "		</tr>";
		h += "		<tr>";
		h += "			<td>&nbsp;</td>";
		h += "			<td>" + dateTimeSelect(id+'dropoff', "") + "</td>";
		h += "		</tr>";
		h += "		<tr class='buttons'>";
		h += "			<td>&nbsp;</td>";
		h += "			<td><button id='" + id + "search'>Search</button></td>";
		h += "		</tr>";
		h += "	</table>";
		h += "</div>";
		
		node.innerHTML = h;

		getElement('pickupLocation').onchange = function() {
			if(this.value==''){this.selectedIndex=-1;}
			syncDropoffLocation();
		}
		getElement('dropoffLocation').onchange = function() {
			if(this.value==''){this.selectedIndex=-1;}
			setEdited('dropoffLocation');
		}
		getElement("pickupDateTime.day").onchange = syncDropoffDateTime;
		getElement("pickupDateTime.yearMonth").onchange = syncDropoffDateTime;
		getElement("pickupDateTime.hourMinute").onchange = syncDropoffDateTime;

		var setDropoffDateTimeEdited = function() {
			setEdited('dropoffDateTime');
		}
		
		getElement("dropoffDateTime.day").onchange = setDropoffDateTimeEdited;
		getElement("dropoffDateTime.yearMonth").onchange = setDropoffDateTimeEdited;
		getElement("dropoffDateTime.hourMinute").onchange = setDropoffDateTimeEdited;
		getElement("search").onclick = function(e) {
			if (validate()) {
				
				var options = {
					countryCode : dl.countryCode,
					pickupLocation : getValue('pickupLocation'),
					dropoffLocation : getValue('dropoffLocation'),
					pickupDate : getDateUrl('pickup'),
					dropoffDate : getDateUrl('dropoff')
				}
				jQuery(".dlSearchResults").dlSearchResults(options);
				return true;
			}
			else {
				return false;
			}
		}
		
		var pickupDate = new Date();
		pickupDate.setDate(pickupDate.getDate()+1);
		pickupDate.setHours(10);
		pickupDate.setMinutes(0);
		pickupDate.setSeconds(0);
		setDate('pickup', pickupDate);

		syncDropoffDateTime();
		
		this.selectLocation = selectLocation;
	}

	
	return this.each(function(){
		init(this, {})
	});
	
};

