﻿//Global Variables------------------ Start ------------------------//
var map = null;
var baseLayer = null;
var polyLayer = null;
var Proxy = new svcProxy("Handlers/");
var y$ = jQuery.noConflict();
var searchInput = new Array(2);
var searchInputDisplay;
var searchResults = new Array(2);
var historyFlag = false;

var buyFranchise = '<div class="buy"> \
						<span class="facebox_header">No Locations Nearby</span> \
						<a href="#close" class="close_buy">close</a> \
						<span class="facebox_content"> \
							<p class="blue">There are no additional locations to serve you at this time.</p> \
							<p>However if you would like to learn about franchise opportunities with  \
							   <b>TWO MEN AND A TRUCK&reg;</b> in this area, please visit our \
							   <a href="/franchiseopportunites/">Franchise Opportunities</a> page \
							   or call us at 1-800-345-1070. \
							 </p> \
						 </span> \
						<a href="/franchiseopportunities/" class="buy_learnmore">learn more</a> \
					</div>'


var ApplicationError = '<div class="error"> \
						<span class="facebox_header_err">Sorry! there\'s a problem</span> \
						<a href="#close" class="close_error">close</a> \
						<ul> \
							<li>	\
								<img src="content/images/warning_button.gif" class="warning" /> \
							</li>	\
							<li>	\
								<span class="facebox_content_err"> \
								<p class="orange">You have to use a valid zip code</p> \
								<p> Please enter a 5-digit zip code and try again. \
								 </p> \
								</span> \
							</li>	\
					   </div>'

//Global Variables------------------ End --------------------------//

//DEFAULT JAVSCRIPT FUNCTIONS CLASSES ------------- Start ------------//

function SetStartUpDefaults(obj) {
	Globals = eval(obj);
}

function pageload(hash) {
	// hash doesn't contain the first # character.
	if (hash) {
		historyFlag = true;
		var arr = hash.split("=");
		var isZip = /(^searchzip$)/.test(arr[0]);
		if (isZip)
		{
			y$("#ziptab").click();
			y$("#searchbox").val(arr[1]);
			y$(".search_button").click();
		} else {
			y$("#statetab").click();
			y$(".search_list").val(arr[1]);
			y$(".search_button").click();
		}
	}
}

function setHistoryHashObject(type, val) {
	var hash = type + "=" + val;
	y$.history.load(hash);
	return false;
}

y$(document).ready(function() {
	//set up Bing Map
	map = new VEMap('Map');
	map.LoadMap(new VELatLong(Globals.Latitude, Globals.Longitude), Globals.ZoomLevel, VEMapStyle.Road);
	map.vemapcontrol.SetAnimationEnabled(false);
	map.AttachEvent("ondoubleclick", mapClickCustomHandler);
	baseLayer = new VEShapeLayer();
	map.AddShapeLayer(baseLayer);

	//set up input searchbox to support enter key press and also mask the textbox with the help text
	y$("#searchbox").live("keypress", function(e) {
		if (e.which == 13) {
			y$(".search_button").click();
			return false;
		}
	}).addClass("inputHelpText").textboxhelp({
		help: "enter zip code",
		focuscls: "inputHelpText"
	});

	//initiate search action tie in event handlers for search
	y$(".search_button").live("click", function() {
		//selector to determine if this is a state or zipcode search
		//is the zip tab the active tab?
		if (y$("#ziptab").hasClass("zipActive")) { //yes
			var srch = y$("#searchbox").val();
			var isValidZip = /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(srch);
			if (isValidZip) //valid entry
			{
				y$(".left_header > span").html("Search results for " + srch);
				showLoader();
				Proxy.invoke("MapHandler.ashx", y$("#searchbox").val(), DisplaySearchResults, DisplayErrorSearch);
				setHistoryHashObject("searchzip", y$("#searchbox").val()); //store this search in our history hash
			}
			else //show error
			{
				showErrorBox("Zipcode entry was not valid!", "Your entry of " + srch + " was not valid because all entries must numeric and entered as 5 digits! ");
			}
		} else { //nope, so state tab is active
			y$(".left_header > span").html("Search results for " + y$(".search_list :selected").text());
			showLoader();
			Proxy.invoke("MapHandler.ashx", y$(".search_list").val(), DisplaySearchResults, DisplayErrorSearch);
			setHistoryHashObject("searchstate", y$(".search_list").val()); //store this search in our history hash
		}

		return false;
	});

	//FROM tab click handler 
	y$("#ziptab").live("click", function() {

		y$(".search_box").show();
		y$(".search_list").hide();

		if (y$(this).hasClass("zipActive"))
			return false; //tab is already active

		//toggle tab state
		y$(this).addClass("zipActive");
		y$("#statetab").removeClass("stateActive").addClass("state");

		y$(".search_text").html("Find a store by Zip Code:");

		if (searchInput[0] != null) { //we already searched this and have stored data so show it

			ClearMap(polyLayer); //clear the poly layer if its there
			y$(".left_header > span").html("Search results for " + searchInput[0]);
			y$("#searchbox").val(searchInput[0]).removeClass("inputHelpText");
			DisplaySearchResults(searchResults[0]);
			setHistoryHashObject("searchzip", y$("#searchbox").val());  //store this search in our history hash because our tabs can cache the prev result
		}
		else {
			//clear the search box
			y$("#searchbox").val("").addClass("inputHelpText").textboxhelp({
				help: "enter zip code",
				focuscls: "inputHelpText"
			});

		}

		return false;
	});


	//to tab click handler
	y$("#statetab").unbind().bind("click", function() {

		y$(".search_list").show();
		y$(".search_box").hide();

		if (y$(this).hasClass("stateActive"))
			return false; //tab is already active

		//toggle tab state
		y$(this).addClass("stateActive");
		y$("#ziptab").removeClass("zipActive").addClass("zip");

		y$(".search_text").html("Find a store by State: ");


		if (searchInput[1] != null) { //we already searched this and have stored data so show it
			showLoader();
			y$(".left_header > span").html("Search results for " + searchInputDisplay); //searchInput[1]); ***this should display the nice name not abbr
			y$(".search_list").val(searchInput[1]);
			DisplaySearchResults(searchResults[1]);
			setHistoryHashObject("searchstate", y$(".search_list").val()); //store this search in our history hash because our tabs can cache the prev result
		}

		return false;
	});

	//load in the html for the li items from the file
	y$("#liElemsHTMLContainer").load("Html/list.htm");
	
	//set up history support
	y$.history.init(pageload);

	//fire off request for zip code search if a zip is provided via querystring
	if (Globals.Zip != null && Globals.Zip.length > 0) {
		//activate the tab since its not the default
		if (historyFlag == false) {
			y$("#ziptab").click();
			y$("#searchbox").removeClass("inputHelpText").val(Globals.Zip);
			y$(".search_button").click();
		}
	} else if (Globals.State != null && Globals.State.length > 0) {  //fire off request for state search if abbr code passed in
		if (historyFlag == false) {
			y$(".search_list").val(Globals.State);
			y$(".search_button").click();
		}
	}

	//geocode IP if active
	if (Globals.IPGeocodeIsActive)
		Proxy.invoke("IPHandler.ashx", null, fnNullResponse, DisplayErrorSearch); //all null as we dont want feedback on this!
});


//this is a "cleaner" way to handle the incoming url senerio since, technically altering the url in the browser is usually
//considered "illegal" in browser terms due to hijacking and spam/cross site scripting so if we wanted to have nicely formatted
//urls we could use this to parse the incoming url and repost to "clean it up" however, that comes with a servere performance
//penality so we can leave this unless we are running IIS7 or Isapi_filer rewriters...
//function fnIncomingUrl()
//{
//	var url;
//	url = document.location.href.split("?");
//	if (url) {
//		if (url.length > 1) {
//			if (Globals.Zip) {
//				//document.location.href = url[0] + "#zip=" + Globals.Zip;
//				setHistoryHashObject("zip", Globals.Zip);
//			}
//			else {
//				//document.location.href = url[0] + "#state=" + Globals.State;
//				setHistoryHashObject("state", Globals.State);
//			}
//		}
//	}
//}

function mapClickCustomHandler(e) {
	var x = e.mapX;
	var y = e.mapY;
	pixel = new VEPixel(x, y);
	LL = map.PixelToLatLong(pixel);

	map.DeleteRoute();
	showLoader();
	Proxy.invoke("MapHandler.ashx", LL.Latitude + "," + LL.Longitude + "," + e.zoomLevel, DisplaySearchResultsClickMap, DisplayErrorSearch);
	return true;
}

function DisplaySearchResultsClickMap(ret) {

	if (ret.searchParam == "NNN") { //no results so show error
		hideLoader();
		y$.facebox(buyFranchise);
		y$("#facebox .close_buy").unbind("click").bind("click", function() {
			y$.facebox.close();
			return false;
		});
		return false;
	}

	if (ret.searchType == 2) { //state search so set the tab to state
		y$("#statetab").click();
		if (ret.searchParam != null) {
			y$(".search_list").val(ret.searchParam);
			setHistoryHashObject("searchstate", ret.searchParam); 
		}
	} else { //set it to zip
		ClearMap(polyLayer);
		y$("#ziptab").click();
		y$("#searchbox").val(ret.searchParam);
		setHistoryHashObject("searchzip", ret.searchParam); 
	}
	y$(".left_header > span").html("Search results for " + ret.searchParam);
	DisplaySearchResults(ret);
}



function DisplaySearchResults(ret) {
	//set the tracking objects
	//set the global search arrays for tab toggle *** refactor this out phase II
	if (y$("#ziptab").hasClass("zipActive")) { //from tab is active
		searchInput[0] = y$("#searchbox").val();
		searchResults[0] = ret;
	} else {
		searchInput[1] = y$(".search_list").val();
		searchInputDisplay = y$(".search_list :selected").text();
		searchResults[1] = ret;
	}

	if (typeof ret.Poly != 'undefined') { //we have a polygon from a state search so render it!
		y$.each(ret.Poly, function(i, n) {
			if (i == "Coordinates")
			AddPolygonOverlay(n);
		});
	}
	
	//clear existing list
	y$("#list-results").empty();

	//set the left container
	y$.each(ret.List, function(i, n) {
		var elem = y$("#liElemsHTMLContainer").html();
		elem = ReplaceToken(elem, "[LICLASS]", ((i % 2 == 0) ? "no" : "highlight"));
		elem = ReplaceToken(elem, "[LIST_NUMBER]", (i + 1));
		elem = ReplaceToken(elem, "[NAME]", "TWO MEN AND A TRUCK&#174;");
		elem = ReplaceToken(elem, "[DISTANCE]", (typeof (n.Distance) !== 'undefined' && n.Distance != null) ? n.Distance.toString() : "");
		elem = ReplaceToken(elem, "[ADDRESS]", n.Address.toString());
		elem = ReplaceToken(elem, "[CITY]", n.City.toString());
		elem = ReplaceToken(elem, "[STATE]", n.State.toString());
		elem = ReplaceToken(elem, "[ZIP]", n.ZipCode.toString());
		elem = ReplaceToken(elem, "[PHONE]", n.Phone.toString());
		elem = ReplaceToken(elem, "[WEBSITE]", (typeof (n.Url) !== 'undefined' && n.Url != null) ? fnCheckWebsite(n.Url.toString()) : fnCheckWebsite(null));
		elem = ReplaceToken(elem, "[ESTIMATE]", fnBuildEstimateUrl(n.Id.toString()));
		elem = ReplaceToken(elem, "[GEOX]", n.Latitude.toString());
		elem = ReplaceToken(elem, "[GEOY]", n.Longitude.toString());
		y$(elem).appendTo("#list-results");
	});
	
	//set the map points
	setMapPoints(ret.List, ret.Centroid);
	
	//hide the loader
	hideLoader();

	if (ret.BuyFranchiseFlag) {  //show the Buy A Franchise window
		y$.facebox(buyFranchise);
		y$("#facebox .close_buy").unbind("click").bind("click", function() {
			y$.facebox.close();
			return false;
		});
	}
}

function fnBuildEstimateUrl(id) {
	 if (id != null) {
	 	return "<a href='Estimate/EstimateRequest.aspx?id=" + id + "&Email=" + Globals.Email + "&Zip=" + Globals.Zip + "&MoveMonth=" + Globals.MoveMonth + "&MoveDay=" + Globals.MoveDay + "&MoveYear=" + Globals.MoveYear + "'>Get an estimate</a>";
	 }
}

function ReplaceToken(currString, token, val) {
	var i = currString.indexOf(token);
	var r = "";
	if (i == -1) return currString;
	r += currString.substring(0, i) + val;
	if (i + token.length < currString.length)
		r += ReplaceToken(currString.substring(i + token.length, currString.length), token, val);
	return r;
}

function fnCheckWebsite(s) {
	var webUrlString = "";
	if (s != null && s.toString().length > 0) {
		if (s.toString().indexOf("//") > 0) {
			webUrlString = "<a href='" + s + "'>More information</a>&nbsp;|&nbsp;"
		} else {
			webUrlString = "<a href='http://" + s + "'>More information</a>&nbsp;|&nbsp;"
		}

		return webUrlString;
	}

	return webUrlString;
}


function DisplayErrorSearch(ret) {
	hideLoader();
    if (ret == "Bad Request") {
        showErrorBox("Whoops! Search Failed...", "Invalid Search Criteria");
       }
    else if (ret.searchParam == "NNN") { //no results so show error
		hideLoader();
		y$.facebox(buyFranchise);
		y$("#facebox .close_buy").unbind("click").bind("click", function() {
			y$.facebox.close();
			return false;
		});
		return false;
    }
    else {
		try
		 {
			var err = eval("(" + ret + ")");
    		showErrorBox("Whoops! Search Failed...", "Reason for Error: " + err.ERROR);
		 }
		 catch(errrr)
		 {
		 	showErrorBox("Whoops! Search Failed...", "Reason for Error: " + errrr.description);
		 }
    }
}

function AddPolygonOverlay(pnts) {

	//first clear out the existing polyLayer if there is one active
	ClearMap(polyLayer);

	polyLayer = new VEShapeLayer();
	polyLayer.SetTitle("OVERLAY");
	map.AddShapeLayer(polyLayer);
	
	var arr = new Array();
	y$.each(pnts, function(i, n) {
		arr.push(new VELatLong(this.Latitude, this.Longitude, 0, VEAltitudeMode.RelativeToGround));
	});

	var myPolygon = new VEShape(VEShapeType.Polygon, arr);
	myPolygon.HideIcon();
	var color = new VEColor(255, 0, 0, 0.3); //Red
	myPolygon.SetFillColor(color);
	myPolygon.SetLineWidth(2);
	myPolygon.SetLineColor(color);

	polyLayer.AddShape(myPolygon);
}


function setMapPoints(rows, cntr) {
	var centroid;
	ClearMap(baseLayer);
	baseLayer = new VEShapeLayer();
	baseLayer.SetTitle("DEFAULT");
	map.AddShapeLayer(baseLayer);
	var shps = new Array();
	var x=null;
	y$.each(rows, function(i, n) {
		x = new VELatLong(n.Latitude, n.Longitude);
		var shape = new VEShape(VEShapeType.Pushpin, x);
		shape.SetCustomIcon("<div class='pinStyle DEFAULT'><div class='text'>" + (i + 1) + "</div></div>");
		shape.SetDescription('<div class="balloon">' +
		                        '<div class=\"balloon_top\">' +
		                            '<div class=\"balloon_title\">TWO MEN AND A TRUCK&#174;</div>' +
		                            '<div class=\"balloon_description\">' +
		                                '<span class=\"spAddress\">' + n.Address + '</span>' +
		                                '<br />' +
		                                '<span class=\"spAddRest\">' + n.City + ', ' + n.State + ' ' + n.ZipCode + '</span>' +
		                                '<br />' +
		                                '<strong>Phone:</strong> ' + n.Phone +
		                            '</div>' +
		                        '</div>' +
		                        '<div class=\"balloon_bottom\">' +
									'<br />' +
		                            '<span class="web">' + fnCheckWebsite(n.Url) + '</span><span class="web">' + fnBuildEstimateUrl(n.Id) + '</span>' +
		                            '<div class="addy_callout">' +
		                                '<label for="txtAddress">Start: </label>' +
				                        '<input id="txtAddress" type="text" />&nbsp;' +
				                        '<a href="#GetDirections" class="srchDirections hide" onclick="fnCallGetDirectionsBalloon(this,' + n.Latitude + ', ' + n.Longitude + ')">go</a>' +
		                            '</div>' +
		                        '</div>' +
		                    '</div>');
		shps.push(shape);
	});

	//if this search was a result of the centroid buffer then mark the map with the centroid marker so the distance param makes sense
	//to see if we need to display the marker pin check and see if the centroid object has scope and if the Lat property is populated
	if (typeof cntr == 'object' && typeof cntr.Latitude == 'number') {
		var cntrPoint = new VELatLong(cntr.Latitude, cntr.Longitude);
		centroid = new VEShape(VEShapeType.Pushpin, cntrPoint);
		centroid.SetCustomIcon("<div class='pinStyleCentroid'><div class='text'></div></div>");
		centroid.SetDescription('<div class="balloon">' +
		                        '<div class=\"balloon_top\">' +
		                            '<div class=\"balloon_title\">TWO MEN AND A TRUCK&#174;</div>' +
		                            '<div class=\"balloon_description\">' +
		                                '<br/>' +
		                                '<strong>You Are Here!</strong><br/>' +
		                                'This marker represents the center point of the zip code you searched since there is not a location in your immediate area here are the locations close!' +
		                            '</div>' +
		                        '</div>' +
		                    '</div>');
		shps.push(centroid);
	}
	
	baseLayer.AddShape(shps);
	//if there is only one record, don't zoom in too close.  5 mile radius is plenty close-enough
	var rect;
    //selector to determine if this is a state or zipcode search
	if (y$("#ziptab").hasClass("zipActive")) { //zip search (
		if (shps.length == 1)
		//for just one result, zoom to a 5 mile radius
			rect = fnFiveMileRect(x)
		else  //for multiple results, make sure the boundary is large enough to show all of the results
			rect = baseLayer.GetBoundingRectangle();
		//if there are zero results, this would zoom-out to show the whole earth so only zoom if there are results
		if (shps.length > 0)
			map.SetMapView(rect);
		//added to meet requirement for 1 record zoom plus zoom display
		if (shps.length == 1)
			showBalloon(shps[0]);

		if (centroid) //if the centroid var has scope then show the msgbox per status update meeting
			showBalloon(centroid);
	} else {
		if (polyLayer) {
			rect = polyLayer.GetBoundingRectangle();
			map.SetMapView(rect);
		}
	}
} 

function fnFiveMileRect(centerPoint, radius) {
    var minRadius = 0.02;
    var upperLeft = new VELatLong(centerPoint.Latitude - minRadius, centerPoint.Longitude - minRadius);
    var lowerRight = new VELatLong(centerPoint.Latitude + minRadius, centerPoint.Longitude + minRadius);
    return new VELatLongRectangle(upperLeft, lowerRight);
}

//used to set the zoom in fuction TODO -  make this a jQuery plugin
function fnSelectandZoom(obj) {
	var id = parseInt(y$(obj).parent().parent().children("td:first").children("span").text());
	for (var i = 0; i < map.GetShapeLayerCount(); i++) {
		var TargetLayer = map.GetShapeLayerByIndex(i);
		if (TargetLayer.GetTitle() == "DEFAULT") {
			var shape = TargetLayer.GetShapeByIndex(parseInt(id - 1));
        	map.SetCenterAndZoom(new VELatLong(shape.Latitude, shape.Longitude), 16);
			showBalloon(shape);
		}
	}

	return false;
}

function showBalloon(ob) {
	try {
		map.ShowInfoBox(ob);
	}
	catch (e) {
		showErrorBox("Bing Map Error", e.description);
	}

}

function fnClearMap() {
	map.DeleteRoute();
	if (polyLayer) // if the polygon layer is not null then remove it and set it null
	{
		map.DeleteShapeLayer(polyLayer);
		polyLayer = null;
	}

	if (baseLayer) // if the polygon layer is not null then remove it and set it null
	{
		map.DeleteShapeLayer(baseLayer);
		baseLayer = null;
	}
	
	y$(".left_header > span").html("");
}

function ClearMap(layer) {
	if (layer != null) {
		map.DeleteShapeLayer(layer);
		layer = null;
	}
}


//Global Error Box
function showErrorBox(msgTitle, msgBody) {
	hideLoader();
	y$.facebox(ApplicationError);
	y$("#facebox .content").find(".orange").html(msgTitle);
	y$("#facebox .content").find("p:last").html(msgBody);
	y$("#facebox .close_error").unbind("click").bind("click", function() {
		y$.facebox.close();
		return false;
	});
}

function showLoader() {
	y$(".load_graphic").css("height", parseInt(getPageScroll()[1]) + parseInt(getPageHeight()));
	y$(".load_graphic").show();
	//setTimeout(null, 1);
}

function hideLoader() {
	y$(".load_graphic").hide();
}

function getPageScroll() {
	var xScroll, yScroll;
	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
		xScroll = self.pageXOffset;
	} else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
		xScroll = document.documentElement.scrollLeft;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
		xScroll = document.body.scrollLeft;
	}
	return new Array(xScroll, yScroll)
}

// Adapted from getPageSize() by quirksmode.com
function getPageHeight() {
	var windowHeight
	if (self.innerHeight) {	// all except Explorer
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowHeight = document.body.clientHeight;
	}
	return windowHeight
}

function fnNullResponse() {
	return false;
}