// This code is copyright 2007 by Mike DeGraw-Bertsch.  All rights reserved.
// If you use this code for your own site, great!  But please provide credit
// to the author and include a clear link to nyccabfare.com.

var gm = google.maps;
var gDir, gDirRender, geocoder, gAds;
var oMap, oMapOpts, elMap, latlng, marker1, marker2, activeMarker, bPOISelected, wait;
var oReqData=oDirResp=oRoute=oResultData={};
var arrPoints=cityMarkers=[];
var form, cityCode, requestString;
var bSubmitPending =false;
var imgMarker1 = "maps/dd-start.png", imgMarker2 = "maps/dd-end.png";

Array.prototype.inArray = function(value) {
	for (var i=0; i < this.length; i++) 
		if (this[i] === value) return true;
	return false;
}

function init() {
	if (!form) form = document.forms["entryForm"];
	createMap(parseFloat(form["lat"].value), parseFloat( form["lng"].value), parseFloat(form["zoom"].value));
	if (cityCode!="") attachEvents();
	else showCityMarkers();
	
}

function createMap(lat, lng, scale) {
	if (!form) form = document.forms["entryForm"];
	cityCode = form["city_code"].value;
	var latlng = new gm.LatLng(lat,lng);
	var navCtrl = gm.NavigationControlStyle.DEFAULT; 
	oMapOpts = {
		navigationControl:true, navigationControlOptions:{style:navCtrl}, 
		center:latlng, zoom:scale, 
		mapTypeId:gm.MapTypeId.ROADMAP, 
		mapTypeControl:false, 
		backgroundColor:"#dddddd"
	};
	if (!(elMap = document.getElementById("map"))) return
	oMap = new gm.Map(elMap, oMapOpts);
	
	/*var gAdsOpts = {maxAdsOnMap:3, style:'adunit', channel:'2466673891'};
	gAds = new GAdsManager(oMap, "9556450948334694", gAdsOpts);
	gAds.enable();*/
}

function showCityMarkers(){
	if (window.oCities==undefined) return;
	cityMarkerCount=0;
	for (var key in oCities)
	{
		latlng = new gm.LatLng(oCities[key].latlng[0], oCities[key].latlng[1]);
		cityMarkers[cityMarkerCount] =  new gm.Marker({position:latlng, map:oMap, title:key});
		var code=oCities[key].code;
		gm.event.addListener(cityMarkers[cityMarkerCount], 'click', cityClick);
		cityMarkerCount++;
	}
}

function cityClick(e){
	citycode = oCities[this.title].code;
	rootPath = (tmp=form.defaultDomain.value+form.rootPath.value) ? tmp : "taxiwiz.com";
	urlLang = (tmp=form.lang.value) ? "?lang="+tmp : "";
	if (citycode) location.href = "http://" +citycode+"."+rootPath+urlLang;
}

function changeCity(box) {
	citycode = box.value;
	rootPath = (tmp=form.defaultDomain.value+form.rootPath.value) ? tmp : "taxiwiz.com";
	urlLang = (tmp=form.lang.value) ? "?lang="+tmp : "";
	if (citycode) location.href = "http://" +citycode+"."+rootPath+urlLang;
}

function changeLang(box) {
	if (box.value) location.href = box.value;
}

function attachEvents()
{
	if (elStart = form.elements.startaddr) gm.event.addDomListener(elStart, 'keypress', chkKey)
	if (elEnd = form.elements.endaddr) gm.event.addDomListener(elEnd, 'keypress', chkKey)
	gm.event.addListener(oMap, 'click', mapClick);
	gDir = new gm.DirectionsService;
	gDirRender = new gm.DirectionsRenderer;
	geocoder = new gm.Geocoder();
	marker1 = new gm.Marker({position:oMap.center, map:oMap, icon:imgMarker1, draggable:true, visible:false});
	marker2 = new gm.Marker({position:oMap.center, map:oMap, icon:imgMarker2, draggable:true, visible:false});
	gm.event.addListener(marker1, 'dragend', function() {geocodeLat2Addr(marker1.getPosition(),1); });
	gm.event.addListener(marker2, 'dragend', function() {geocodeLat2Addr(marker2.getPosition(),2); });
}

function chkKey(e)
{
	ev = e||window.event;
	if (ev.keyCode==13) {
		if ( (!arrPoints[0]) ? (arrPoints[1]) : (!arrPoints[1]) ) {bSubmitPending=true;}
	}
}

function geocodeLat2Addr(pos,n) {
	activeMarker = n;
	geocoder.geocode({latLng: pos}, function(){geoLat2AddrResp.apply(this, [arguments[0],arguments[1], n])} ); //overload args with marker#
}

function geocodeAddr2Lat(elem,n) {
	sAddr = elem.value;
	if (sAddr=="") {clearPoint(n);return;}
	bPOISelected = (elem.type=="select-one") ? true : false;
	clearCoelement(elem);
	addCity = form.ac.value;
	sAddr+=addCity; //if (sAddr.split(",").length == 1) sAddr+=addCity;
	activeMarker = n;
	sAddr=unescape(sAddr);
	geocoder.geocode({address: sAddr}, function(){geocodeAddr2LatResp.apply(this, [arguments[0],arguments[1], n])} ); //overload args with marker#
}

function geoLat2AddrResp() {
	oResponse = arguments[0];
	geoStatus = arguments[1];
	n = (arguments[2] || activeMarker);
	if (geoStatus!="OK") {clearPoint(n); pointError("- The selected point is not valid. Please select another.",geoStatus); return}
	arrPoints[n-1] = setPointData(oResponse);
	sAddr = arrPoints[n-1].formatted_address;
	dispAddress(sAddr, n);
	moveMarker(arrPoints[n-1], n);
}

function geocodeAddr2LatResp() {
	oResponse = arguments[0];
	geoStatus = arguments[1];
	n = (arguments[2] || activeMarker);
	if (geoStatus!="OK") {clearPoint(n); pointError("- Unknown address, please try another."); return}
	if (!bPOISelected) dispAddress(oResponse[0].formatted_address, n);
	if (geoStatus=="OK") {
		moveMarker(oResponse[0].geometry.location, n);
		setPointData(oResponse);
	}
	else moveMarker(null, n);
	checkSubmitPending();
}

function setPointData(oResp)
{
	obj = {};
	if (oResp[0].geometry.location) obj = oResp[0].geometry.location;
	obj.address_components = oResp[0].address_components;
	obj.formatted_address = oResp[0].formatted_address;
	obj.locality = getLocality(oResp[0]);
	return obj;
}

function getLocality(oGeocode) {
	sLocality = sSubLocality = "";
	if (oGeoAddr = oGeocode.address_components) {
		for (i=0;i<oGeoAddr.length;i++) {
			if ((oGeoAddr[i].types.inArray("political")) && (oGeoAddr[i].types.inArray("locality"))) 
				sLocality = oGeoAddr[i]["short_name"];
			if ((oGeoAddr[i].types.inArray("political")) && (oGeoAddr[i].types.inArray("sublocality"))) 
				sSubLocality = oGeoAddr[i]["short_name"];
		}
	}
	return (sSubLocality) ? sSubLocality : ((sLocality) ? sLocality : "");
}

function dispAddress(str, n) {
	objDisp = (n==1) ? form.startaddr : form.endaddr;
	objDisp.value = str;
	clearCoelement(objDisp);
}

function clearElem(elem)
{
	if (elem.type=="select-one") elem.selectedIndex=0;
	if (elem.type=="text") elem.value="";
}

function clearCoelement(elem){
	switch (elem.name){
		case "startapt": elemReset="startaddr";break;
		case "startaddr": elemReset="startapt";break;
		case "endapt": elemReset="endaddr";break;
		case "endaddr": elemReset="endapt";break;
	}
	clearElem(form[elemReset])
}

function moveMarker(latlng, n){
	oMarker = window["marker"+n];
	if (latlng){
		oMarker.setPosition(latlng);
		oMarker.setVisible(true);
	}
	else oMarker.setVisible(false);
	arrPoints[n-1]=latlng;
}

function clearPoint(n)
{
	arrPoints[n-1] = null;
	oMarker = window["marker"+n];
	oMarker.setVisible(false);
	preElem = (n==1) ? "start" : "end";
	clearElem(form[preElem+"apt"]);
	clearElem(form[preElem+"addr"]);
	clearElem(form[preElem+"addr"]);
}

function mapClick(event) {
	if (arrPoints[0] && arrPoints[1]) return;
	n = (arrPoints[0]) ? 1 : 0;
	oMarker = window["marker"+(n+1)];
	arrPoints[n] = event.latLng;
	oMarker.setPosition(arrPoints[n]);
	oMarker.setVisible(true);
	geocodeLat2Addr(arrPoints[n], n+1);
}

function mapSubmit(form)
{
	if (wait) {submitError("- Please wait"); return false};
	if (cityCode=='') {submitError("- Please first select a city.");return false};
	if (bSubmitPending) return; //if ( (!arrPoints[0]) ? (arrPoints[1]) : (!arrPoints[1]) ) {bSubmitPending=true; wait = 1; return false;}
	if (!(arrPoints[0]) && !(arrPoints[1])) {clearPoint(1); clearPoint(2); submitError("- Please select Starting/Destination points by clicking on the map or entering them above.");return false};
	if (!arrPoints[0]) {clearPoint(1); submitError("- Please select a Starting Point by clicking on the map or entering it above.");return false};
	if (!arrPoints[1]) {clearPoint(2); submitError("- Please select a Destination by clicking on the map or entering it above.");return false};
	form.btnSubmit.disabled = wait = 1;
	directionsRequest(arrPoints);
	return false;
}

function checkSubmitPending()
{
	if (bSubmitPending) {
		bSubmitPending=false;
		form.btnSubmit.disabled = wait = 0;
		if ((arrPoints[0]) && (arrPoints[1])) mapSubmit(form);
	}
}

function directionsRequest(arrPts) {
	var req = {origin: arrPts[0], destination: arrPts[1], travelMode: gm.DirectionsTravelMode.DRIVING, unitSystem: gm.DirectionsUnitSystem.METRIC};
	gDir.route(req, directionsResponse);
}

function directionsResponse() {
	oDirResp = arguments[0];
	statusCode = arguments[1];
	if (statusCode!="OK") {submitError("- Directions cannot be found. Please try again later.",statusCode); return}
	if (!((oDirResp.routes[0])&&(oRoute=oDirResp.routes[0].legs[0]))) {submitError("- Directions cannot be found for the route selected. Please try again."); return}
	oReqData["dist"] = oRoute.distance.value;
	oReqData["duration"] = oRoute.duration.value;
	oReqData["turns"] = oRoute.steps.length-1;
	oReqData["startCity"] = arrPoints[0].locality; //getLocality(oRoute.start_geocode);
	oReqData["endCity"] = arrPoints[1].locality; //getLocality(oRoute.end_geocode);
	sendReq(oReqData);
	//clearPoint(1);
	//clearPoint(2);
	form.btnSubmit.disabled = wait = 0;
}

function sendReq(oReq) {
	cityID = cityCode;
	lang = form.lang.value;
	//locale = form.locale.value;
	startPOI = form.startapt.value;
	endPOI = form.endapt.value;
	if (form.startapt.selectedIndex!=0) oResultData.startPOIName = form.startapt.options[form.startapt.selectedIndex].text;
	if (form.endapt.selectedIndex!=0) oResultData.endPOIName = form.endapt.options[form.endapt.selectedIndex].text;
	
	routeUrl = form.rootPath.value+"maps/beta_route.php"
	e=escape;
	requestString = routeUrl+"?city_id="+e(cityID)+"&lang="+e(lang)+"&startpnt="+e(arrPoints[0])+"&endpnt="+e(arrPoints[1]); //"&locale="+e(locale)+
	requestString+= "&d="+e(oReq['dist'])+"&t="+e(oReq['turns']-1)+"&s="+e(oReq['duration']);
	requestString+= "&startcity="+e(oReqData["startCity"])+"&endcity="+e(oReqData["endCity"]);
	requestString+= "&startapt="+e(startPOI)+"&endapt="+e(endPOI);
	if (form.day && form.hour) requestString+= "&day="+e(form.day.value)+"&hour="+e(form.hour.value);
	if (form.passengers) requestString+= "&pass="+e(form.passengers.value);
	//alert(requestString);
	downloadUrl(requestString, getResp, true);
}

function getResp() {
	oData = arguments[0]; //statusCode = arguments[1];
	if (!(xmlTrip = oData.getElementsByTagName("trip"))) {submitError("- Directions cannot be found. Please try again later."); return}
	for (i=0; i<xmlTrip[0].attributes.length; i++) {
		oResultData[xmlTrip[0].attributes[i].nodeName] = xmlTrip[0].attributes[i].nodeValue;
	}
	showResultsPage();
}

function showResultsPage() {
	if (!oResultData) {submitError("- Directions cannot be found. Please try again later."); return}
	arrElems = ["entryFields", "resultsHdr", "results", "resultsTxt", "cityName", "routeInfo", "footer"]
	for (i=0; i<arrElems.length; i++)
		window["el"+arrElems[i]] = ID(arrElems[i]);

	var report = "<h2>" +oResultData["title"]+ "</h2><p id='report'>" +oResultData["stats"];
	if (oResultData["flat"]) report += " " +oResultData["flat"];
	else if (oResultData["surcharge"]) report += " " +oResultData["surcharge"];
	report += "</p>";
	for (i=0,start='',end='';i<2;i++){ //shorthand addr for disp
		start += arrPoints[0].address_components[i].short_name+' ';
		end += arrPoints[1].address_components[i].short_name+' ';
	}
	if (oResultData.startPOIName) start=oResultData.startPOIName;//form.startapt.options[form.startapt.selectedIndex].text;
	if (oResultData.endPOIName) end=oResultData.endPOIName;//form.endapt.options[form.endapt.selectedIndex].text;

	elcityName.innerHTML = form.city_name.value;
	elrouteInfo.innerHTML = "<h2 class='inline'>"+start+" </h2><h1 class='inline'>\u2192</h1><h2 class='inline'> "+end+"</h2>"; //\u00BB 
	//elrouteInfo.innerHTML = "<h2>"+oRoute.start_geocode.formatted_address+" <i>to</i><br>"+oRoute.end_geocode.formatted_address+"</h2>";
	elresultsTxt.innerHTML = report;
	elresults.className = "floatL";
	elresultsHdr.className = "on";
	elfooter.className = "on";
	elMap.className = "mapReg";
	oMap = new gm.Map(elMap, oMapOpts);
	gDirRender.setMap(oMap);
	gDirRender.setDirections(oDirResp);	//gDirRender.setPanel(eldirSteps)); //show steps
	elentryFields.className = "off"; //ie float bug - set after map
}

function ID(o) {
	if (ret = document.getElementById(o)) return ret;
	return false;
}

function pointError(defaultError, gError){
	if (gError=="ZERO_RESULTS") defaultError="- The selected point is invalid."
	if (!(elError = document.getElementById("errors"))) {alert(defaultError); return}
	elError.className  = 'm15';
	elError.innerHTML = defaultError;
	form.btnSubmit.disabled = wait = 0;
	flickerBack();
}

function submitError(defaultError, gError) {
	if (gError=="ZERO_RESULTS") defaultError="- Driving directions cannot be found. Please select different Starting/Ending Points.";
	if (gError=="NOT_FOUND") defaultError="- Driving directions cannot be found. Please select different Starting/Ending Points.";
	if (!(elError = document.getElementById("errors"))) {alert(defaultError); return}
	elError.className  = 'm15';
	elError.innerHTML = defaultError;
	form.btnSubmit.disabled = wait = 0;
	flickerBack();
}

function flickerBack() {
 	elError.style.background = '#ffff00';
	setTimeout("elError.style.background = '#000000'", 250);
}

// XMLHTTPrequest funcs
function createXmlHttpRequest() {
 try {
   if (typeof ActiveXObject != 'undefined') {
     return new ActiveXObject('Microsoft.XMLHTTP');
   } else if (window["XMLHttpRequest"]) {
     return new XMLHttpRequest();
   }
 } catch (e) {
   changeStatus(e);
 }
 return null;
}

function downloadUrl(url, callback, bXML) {
 var status = -1;
 var request = createXmlHttpRequest();
 if (!request) return false;
 
 request.onreadystatechange = function() {
   if (request.readyState == 4) {
     try {
       status = request.status;
     } catch (e) {
		submitError("- Sorry, there was an error retrieving directions. Please try again later.")
     }
     if (status == 200) {
       if (bXML) callback(request.responseXML, request.status);
	   else callback(request.responseText, request.status);
       request.onreadystatechange = function() {};
     }
   }
 }
 request.open('GET', url, true);
 try {
   request.send(null);
 } catch (e) {
   changeStatus(e);
 }
};
// End xmlhttp
///////////////

