
var USA_COUNTRY_ID = 223;
var CANADA_COUNTRY_ID = 38;

var INITIAL_ZOOM_LEVEL = 2;
var map;
var mapDiv;
var hoverMsg;
var request;
var infoRequest;

var internetDealerRequest;

var infoWindowMarker;
var infoWindowMarkerPoint;
var allMarkers = new Array();

var	zipCode;
var zipRequest = GXmlHttp.create();
var ZIP_CODE_ZOOM_LEVEL = 11;

var filterCheckboxes;

var countryRequest = GXmlHttp.create();
var countrySelect;

var count = 0;

var COUNTRY_ZOOM_LEVEL = 3;

window.onload = pc_init;

// All javascript body onload functions must be named pc_init
// to allow functionality when user is logged in
function pc_init() {
	if (GBrowserIsCompatible()) {
		request = GXmlHttp.create();
		infoRequest = GXmlHttp.create();
		internetDealerRequest = GXmlHttp.create();
		
		$("#dealerFilterForm").show();
	
		mapDiv = document.getElementById('map');
		$(mapDiv).width(500).height(375).show();
	
		$("#internetDealers").show();
		$("#internetDealerList").height($("#internetDealers").height()-6);
		
		$("#loadingMsg").html("Initializing...");
		
		if (getCookie() && getCookie().save || !getCookie()) {
			$("#rememberMeBox").attr("checked","checked");
		}
		else {
			$("#rememberMeBox").attr("checked","");
		}
		$("#rememberMeBox").bind("click",stateSavePreferenceChangeHandler);
		
		initMapState();
		
		$("#mfgSelector").bind("change",mfgSelectorResponder);
		
		zipCode = document.getElementById("zipCodeInput");
		$(zipCode).bind("click", function() {
			if (this.value == this.defaultValue) {
				this.value = "";
			}
			return true;
		});
		
		initFilterAndLocationOptions();
		hideHoverMessage();
		getDealerInfo();
		getInternetDealerInfo();
	}
	else if (window.location.href.indexOf('noncompat') < 0) {
		window.location += "?noncompat=1";
	}
}

function initMapState() {
	map = new GMap(mapDiv);
	
	var initialCenter = new GLatLng(0, 0);
	var initialZoom   = INITIAL_ZOOM_LEVEL;
	
	var attLat = $(mapDiv).attr('LAT');
	var attLng = $(mapDiv).attr('LNG');
	var attArea= $(mapDiv).attr('AREA');
	
	var cookieState = getCookie();
	if (cookieState && cookieState.save) {
		initialCenter = new GLatLng(cookieState.lat, cookieState.lng);
		initialZoom = cookieState.zoom-0; // force to number
	}
	else if (attLat != null && attLng != null && attArea != null && attArea > 0) {
		initialCenter = new  GLatLng(attLat, attLng);
		initialZoom = getZoomLevelForCountrySize(Number(attArea));
	}
	
	map.setCenter(initialCenter, initialZoom);
	
	GEvent.addListener(map, 'moveend', getDealerInfo);
	GEvent.addListener(map, 'infowindowclose', function() {
		infoWindowMarker = null;
		infoWindowMarkerPoint = null;
	});
	
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	
	markers = new Array();
}

function initFilterAndLocationOptions() {
	$("#zipBtn").bind("click", getZipCoords);
	$(zipCode).bind("keydown", watchForEnter);
	
	infoWindowContents = document.createElement('DIV');
	infoWindowContents.style.whiteSpace = "nowrap";
	
	countrySelect = document.getElementById("country_select");
	$(countrySelect).bind("change", countrySelectorResponder);
		
	initLocationOptionValues();
		
	$("#dlrFilters input:checkbox").bind("click", closeWindowAndGetDealerInfo);
	
	initCheckboxesFromCookie();
	
	// initialize the brand dropdown
	// We use the cookie, but only if the SELECT isn't already set to something else
	// This could happen if there was a passed-in mfg_id to the page
	var cookieState = getCookie();
	if (cookieState && cookieState.save && $("#mfgSelector").val() == 0) {
		$("#mfgSelector").val(cookieState.mfg_id);
	}
}

function initCheckboxesFromCookie() {
	var cookieState = getCookie();
	if (cookieState && cookieState.save) {
		$("input[name='prod_id']").val(cookieState.prod_id);
		$("input[name='serv_id']").val(cookieState.serv_id);
	}
}

function initLocationOptionValues() {
	var cookieState = getCookie();
	var zipCookie = null;
	
	if (cookieState && cookieState.save) {
		$(countrySelect).val(cookieState.country_id);
		if (cookieState.zip != "default" && ($(countrySelect).val() == USA_COUNTRY_ID || $(countrySelect).val() == CANADA_COUNTRY_ID)) {
			$(zipCode).val(cookieState.zip);
		}
	}
	else {
		$(countrySelect).val($(mapDiv).attr("COUNTRY"));
	}	
}

function showNoProjectorsMessage() {
	/*var html = "<h1>No dealers found</h1>Widen your search area by zooming out or moving the map";
	showHoverMessage(html);*/
	showNoVisibleDealersMessage();
}

function showTooManyProjectorsMessage(n) {
	/*if (n == null) {
		var html =  "<h1>Too many dealers found</h1>";
	}
	else {
		var html = "<h1>"+n+" dealers found</h1>This is too many to be displayed on the map.<br>";
	}
	html += "Narrow your search area by zooming in or moving the map.";
	//html += " or specify some search criteria";
	showHoverMessage(html);*/
	showNoVisibleDealersMessage(n);
}

function showNoVisibleDealersMessage(n) {
	if (n == null) {
		var html =  "<h1>No merchants found</h1>";
	}
	else {
		var html = "<h1>"+n+" merchants found</h1>";
	}
	html += "To see up to 30 merchants, use the check boxes, zoom in, and/or move the map.";
	showHoverMessage(html);
}

function showHoverMessage(h) {
	hoverMsg = document.createElement('DIV');
	var msgPadding = 50;
	hoverMsg.id = "hoverMsg";
	$(hoverMsg).html(h).css("position","absolute").css("zIndex",10);
	
	mapDiv.appendChild(hoverMsg);
	
	hoverMsg.style.left = (($(mapDiv).outerWidth())/2 - ($(hoverMsg).outerWidth())/2) + "px";
	
	hoverMsg.style.bottom = "30px"
	// Align in middle of screen - OLD
	//hoverMsg.style.top = (mapDiv.offsetHeight/2 - hoverMsg.offsetHeight/2) + "px";
	
	$(hoverMsg).bind("click", hideHoverMessage);
}

function hideHoverMessage() {
	if (hoverMsg != null && hoverMsg.parentNode != null) {
		hoverMsg.parentNode.removeChild(hoverMsg);
	}
}

function closeWindowAndGetDealerInfo() {
	map.closeInfoWindow();
	getDealerInfo();
	getInternetDealerInfo();
}

function countrySelectorResponder() {
	$(zipCode).val(zipCode.defaultValue);
	$(countrySelect).blur();
	getCountryCoords();
	getInternetDealerInfo();
}

function mfgSelectorResponder() {
	getDealerInfo();
	getInternetDealerInfo();
}

var reqCount = 0;
var internetReqCount = 0;

function getDealerInfo() {
	reqCount++;
	var localCount = reqCount;
	$("#loadingMsg").html('Loading local merchant locations...');
	hideHoverMessage();
	var mapBounds = map.getBounds();

	saveStateToCookies();
	
	var d = 'swLng='+mapBounds.getSouthWest().lng()
				+'&neLng='+mapBounds.getNorthEast().lng()
				+'&swLat='+mapBounds.getSouthWest().lat()
				+'&neLat='+mapBounds.getNorthEast().lat();
	d += "&"+buildFilterParams();
	var opts = {
		url: "_dealer_json_gen.cfm",
		dataType: "json",
		data: d,
		error: function (req, textStatus, errorThrown) {
			if (req.status == 200) {
				$("#loadingMsg").html("An error occurred when locating local merchants.");
			}
			else {
				$("#loadingMsg").html("A server error occurred when locating local merchants ("+req.status+")");
			}
		},
		success: function(data, textStatus) {
			// pass in localCount so we don't update for older queries
			updateDealerIcons(data, localCount);
		}
	};
	$.ajax(opts);
}

function getInternetDealerInfo() {
	internetReqCount++;
	var localCount = internetReqCount;
	$("#internetLoadingMsg").html("Loading merchants...");
	
	var mapBounds = map.getBounds();
	var d = 'swLng='+mapBounds.getSouthWest().lng()
				+'&neLng='+mapBounds.getNorthEast().lng()
				+'&swLat='+mapBounds.getSouthWest().lat()
				+'&neLat='+mapBounds.getNorthEast().lat();
	d += "&"+buildFilterParams();
	var opts = {
		url: "_dealer_internet_json_gen.cfm",
		dataType: "json",
		data: d,
		error: function (req, textStatus, errorThrown) {
			if (req.status == 200) {
				$("#internetDealerList").html("An error occurred when locating Internet merchants.");
			}
			else {
				$("#internetDealerList").html("A server error occurred when locating Internet merchants ("+req.status+")");
			}
			$("#internetLoadingMsg").html("&nbsp;");
		},
		success: function(data, textStatus) {
			// pass in localCount so we don't update for older queries
			updateInternetDealers(data, localCount);
		}	
	};
	$.ajax(opts);
}

function getSelectedMfgId() {
	return $("#mfgSelector").val();
}

function getSelectedCountryId() {
	return $("#country_select").val();
}


function buildFilterParams() {
	return $("#dealerFilterForm input, #dealerFilterForm select").serialize();
}

function updateInternetDealers(obj, reqNum) {
	if (reqNum < internetReqCount) {
		return false; // this is an old request
	}
	else {
		var dealerList = document.getElementById("internetDealerList");

		if (!obj.error) {
			var totalDealers = obj.dealers.length;
			var dlrHtml = "";
			for (var i = 0; i < obj.dealers.length; i++) {
				dlrHtml += '<div class="dealerIcon">';
			
				var linkHref = "svc_redir.cfm?acc_id="+obj.dealers[i].acc_id+"&mfg_id="+obj.mfg_id;
				var dealerDesc = obj.dealers[i].desc;
			
				if (obj.dealers[i].image.length == 0) {
					dlrHtml += '<a target="_blank" class="noImageAvailable" href="'+linkHref+'" title="'+dealerDesc+'">'+obj.dealers[i].name+'</a>';
				}
				else {
					dlrHtml += '<a target="_blank" href="'+linkHref+'" title="'+dealerDesc+'"><img border="0" src="/dealer_logos/'+obj.dealers[i].image+'"></a>';
				}
				if (obj.dealers[i].rating > 0 || obj.dealers[i].bid.length > 0) {
					dlrHtml +='<div class="dealerRating">';
					if (obj.dealers[i].bid.length > 0) {
						dlrHtml += '<span class="bid">'+obj.dealers[i].bid+'</span>';
					}
					if (obj.dealers[i].rating > 0) {
						dlrHtml += '<a href="/dealer_profile.cfm?dealer_id='+obj.dealers[i].id+'" title="View this merchant&rsquo;s profile">'+ratingToStars(obj.dealers[i].rating)+'</a>';
					}
					dlrHtml += '</div>';
				}
				if (obj.dealers[i].worldwide) {
					dlrHtml += '<div class="internetDealerInfo">Worldwide Merchant</div>';
				}
				dlrHtml += '<a class="internetDealerInfo" href="/dealer_profile.cfm?dealer_id='+obj.dealers[i].id+'" title="View this merchant&rsquo;s profile">Merchant Profile</a>'
				dlrHtml += '</div>';
			}
			$(dealerList).html(dlrHtml);
		
			$("#internetLoadingMsg").html(totalDealers + ' internet merchant' + (totalDealers==1?'':'s'));
		}
		else {
			$(dealerList).html("Error: "+obj.message);
		}
	}
}

function updateDealerIcons(obj, reqNum) {
	if (reqNum < reqCount) {
		return false; // Don't process this old request
	}
	
	var totalDealers = obj.total;
	var shownDealers = obj.dealers.length;
	
	while (allMarkers.length > 0) {
		var m = allMarkers.pop();
		if (infoWindowMarker == null || m != infoWindowMarker) {
			map.removeOverlay(m);
		}
	}
	
	if (infoWindowMarker != null) allMarkers.push(infoWindowMarker);
	if (!obj.error) {
		for (i = 0; i < obj.dealers.length; i++) {
			if (typeof infoWindowMarkerPoint == "undefined" || infoWindowMarkerPoint == null ||
				(infoWindowMarkerPoint.x != obj.dealers[i].longitude && infoWindowMarkerPoint.y != obj.dealers[i].latitude))
			{
				var type = obj.dealers[i].type;
				var dlrMarker = createDealerMarker(obj.dealers[i]);
				if (typeof dlrMarker != "null") {
					allMarkers.push(dlrMarker);
					map.addOverlay(dlrMarker);
				}
			}
		}
		if (shownDealers == totalDealers) {
			$("#loadingMsg").html(((totalDealers==0) ? 'No' : totalDealers) + ' local merchant' + (totalDealers==1?'':'s'));
			if (shownDealers == 0) {
				showNoProjectorsMessage();
			}
		}
		else {
			$("#loadingMsg").html(totalDealers + ' local merchant' + (totalDealers==1?"":"s"));
			showTooManyProjectorsMessage(totalDealers);
		}
	}
	else {
		$("#loadingMsg").html("Error: "+obj.message);
	}
}

function createDealerMarker(dlrObj) {
	var coords = new GLatLng(dlrObj.lat, dlrObj.lng);
	
	var icon = getDealerIconForType(dlrObj.type);
	var html = getInfoWindowHtmlForDealer(dlrObj);
	var marker = new GMarker(coords, icon);
	
	if (html == "") return null;
	
	GEvent.addListener(marker, 'click', function() {
		// If a user clicks another marker while an info window is already open,
		// Then GMaps will open the new window, then close the old one. This means
		// that the 'infowindowclose' event fires immediately after this one, which
		// has the effect of clearing the infoWindowMarker variables. By closing any
		// open window first, we avoid that problem
		map.closeInfoWindow();
		infoWindowMarker = marker;
		infoWindowMarkerPoint = coords;
		marker.openInfoWindowHtml(html);
	});
	
	return marker;
}

function getDealerIconForType(type) {
	if (type == "premium") {
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.image = "/images/maps/bigredmarker.png";
		icon.iconSize = new GSize(25,45);
		icon.shadow  = "images/maps/shadow50big.png";
		icon.shadowSize = new GSize(45,45);
		icon.transparent = "/images/maps/bigredmarkertrans.png";
		icon.iconAnchor = new GPoint(13,44);
		icon.printImage = "/images/maps/bigredmarkerprint.gif";
		icon.mozPrintImage = icon.printImage;
		return icon;
	}
	else if (type == "standard") {
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.image = "/images/maps/medgreenmarker.png";
		icon.iconSize = new GSize(23,37);
		icon.shadow  = "images/maps/shadow50med.png";
		icon.shadowSize = new GSize(42,37);
		icon.transparent = "/images/maps/medgreenmarkertrans.png";
		icon.iconAnchor = new GPoint(12,36);
		icon.printImage = "/images/maps/medgreenmarkerprint.gif";
		icon.mozPrintImage = icon.printImage;
		return icon;
		return icon;
	}
	else {
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.image = "/images/maps/yellowmarker.png";
		return icon;
	}
}

function getInfoWindowHtmlForDealer(dlrObj) {
	
	var dHtml = "";
	var url = dlrObj.url;	
	
	dHtml += '<div class="dealerName">';
	if (url.length > 0) {
		dHtml += '<A HREF="/exit_link_redir.cfm?earl='+escape(url)+'" target="_blank" title="Visit this merchant&rsquo;s web site"><B>'+dlrObj.name+'</B></A>';
	}
	else {
		dHtml += '<b>'+dlrObj.name+'</b>';
	}
	dHtml += "</div>"

	if (dlrObj.rating > 0) {
		dHtml += '<div>'+ratingToStars(dlrObj.rating)+'</div>';
	}
	
	dHtml += '<div>'+dlrObj.address+'</div>';
	
	var phone = dlrObj.phone1;
	if (phone.length > 0) {
		dHtml += "<div>"+phone+"</div>";
	}
	phone = dlrObj.phone2;
	if (phone.length > 0) {
		dHtml += "<div>"+phone+"</div>";
	}
	
	email = dlrObj.email;
	if (email.length > 0) {
		dHtml += '<div><a href="mailto:'+email+'">'+email+'</a></div>';
	}
	
	dHtml += '<div class="profileLink"><a href="/dealer_profile.cfm?dealer_id='+dlrObj.id+'" title="View this merchant&rsquo;s profile">Merchant Profile</a></div>';
	
	return '<div style="white-space:nowrap;">'+dHtml+'</div>';
}

function ratingToStars(r) {
	var html = "";
	for(var s = 1; s <= 5; s++) {
		if (s <= r) {
			html += '<IMG CLASS="star" SRC="/images/red_star_on.gif" BORDER=0>';
		}
		else if ((r - Math.floor(r)) >= 0.5 && s - r <= 0.5) {
			html += '<IMG CLASS="star" SRC="/images/red_star_onoff.gif" BORDER=0>';
		}
		else {
			html += '<IMG CLASS="star" SRC="/images/red_star_off.gif" BORDER=0>';
		}
	}
	return '<span style="white-space:pre">'+html+'</span>';
}

var zipReqCount = 0;
function getZipCoords() {
	zipReqCount++;
	var localCount = zipReqCount;
	var errorTag = document.getElementById("errorMsg");
	$(errorTag).empty().hide();
	
	if (typeof zipCode == "undefined") {
		return false;
	}
	if (zipCode.value.length == 0) {
		$("#errorMsg").html("You did not enter a postal code.");
		return false;
	}
	// Check for numeric entry
	usRegEx = /^ *[0-9A-Za-z ]{5,} *$/; // allow server-side script to clean up the zip, just make sure they entered SOMETHING
	var validPostalCode = usRegEx.test(zipCode.value);
	if (!validPostalCode) {
		$("#errorMsg").html("The postal code is not in the proper format.");
		return false;
	}
	
	saveStateToCookies();
	$("#loadingMsg").html("Loading postal code location...");
	
	var opts = {
		url: "_dealer_zip_xml.cfm",
		dataType: "xml",
		data: {
			"zip": $(zipCode).val()
		},
		error: function (req, textStatus, errorThrown) {
			if (req.status == 200) {
				$("#errorMsg").show().html("An error occurred when locating that postal code.");
			}
			else {
				$("#errorMsg").show().html("A server error occurred when locating that postal code ("+req.status+")");
			}
		},
		success: function(data, textStatus) {
			// pass in localCount so we don't update for older queries
			zoomToZip(data, localCount);
		}
	};
	$.ajax(opts);	
}

function zoomToZip(xmlDoc, reqNum) {
	if (reqNum < zipReqCount) {
		return false;
	}
	
	var errorNodes = xmlDoc.getElementsByTagName('error');
	
	if ($(errorNodes[0]).attr("status") == "FALSE") {
		$("#loadingMsg").html("");
		var latitude = xmlDoc.getElementsByTagName('latitude')[0].firstChild.nodeValue;
		var longitude = xmlDoc.getElementsByTagName('longitude')[0].firstChild.nodeValue;
		map.setCenter(new GLatLng(latitude, longitude), ZIP_CODE_ZOOM_LEVEL);
		map.savePosition();
		if (zipCode.value.length == 6 || zipCode.value.length == 7) {
			$(countrySelect).val(CANADA_COUNTRY_ID);
			getInternetDealerInfo(); // if we fired the whole country change event, then we'd end up recentering on the country
		}
		else {
			$(countrySelect).val(USA_COUNTRY_ID);
			getInternetDealerInfo();
		}
		saveStateToCookies();
		$(mapDiv).focus();
	}
	else {
		var errorMsg = errorNodes[0].firstChild.nodeValue;
		$("#errorMsg").html(errorMsg).show();
	}
}

function watchForEnter(e) {
	if (e.keyCode == 13) {
		getZipCoords();
	}
}

var ctryReqCount = 0;
function getCountryCoords() {
	ctryReqCount++;
	var localCount = ctryReqCount;
	
	$("#loadingMsg").html("Loading country location...");
	$("#errorMsg").empty().hide();

	var country_id = $(countrySelect).val();

	var opts = {
		url: "_dealer_country_xml.cfm",
		dataType: "xml",
		data: {
			"country_id": country_id
		},
		error: function (req, textStatus, errorThrown) {
			if (req.status == 200) {
				$("#errorMsg").show().html("An error occurred when jumping to that country.");
			}
			else {
				$("#errorMsg").show().html("A server error occurred when locating that country ("+req.status+")");
			}
		},
		success: function(data, textStatus) {
			// pass in localCount so we don't update for older queries
			zoomToCountry(data, localCount);
		}
	};
	$.ajax(opts);

	saveStateToCookies();
}

function zoomToCountry(xmlDoc, reqNum) {
	if (reqNum < ctryReqCount) {
		return false;
	}

	var zoomLevel = COUNTRY_ZOOM_LEVEL;
	var errorNodes = xmlDoc.getElementsByTagName('error');
	
	if (errorNodes[0].getAttribute("status") == "FALSE") {
		$("#loadingMsg").html("&nbsp;");
		var latitude = xmlDoc.getElementsByTagName('latitude')[0].firstChild.nodeValue;
		var longitude = xmlDoc.getElementsByTagName('longitude')[0].firstChild.nodeValue;
		var area = xmlDoc.getElementsByTagName('area')[0].firstChild.nodeValue;
		
		zoomLevel = getZoomLevelForCountrySize(area, latitude);
		map.setCenter(new GLatLng(latitude, longitude), zoomLevel);
		map.savePosition();
		$(mapDiv).focus();
	}
	else {
		var errorMsg = errorNodes[0].firstChild.nodeValue;
		$("#errorMsg").show().html(errorMsg);
	}
}

function getZoomLevelForCountrySize(area, latitude) {
	var logBase = 3.3; // (3.3) A smaller number leads to bigger numbers and the view being farther out
	var level = Math.log(area) / Math.log(logBase);
	return 17-Math.max(Math.min(Math.ceil(level),17),8);
}

function stateSavePreferenceChangeHandler() {
	var saveBox = document.getElementById('rememberMeBox');
	
	if (saveBox.checked) {
		saveStateToCookies();
	}
	else {
		clearStateCookies();
	}
}

//
// COOKIE MANAGEMENT FUNCTIONS
//

function saveStateToCookies() {
	if(document.getElementById("rememberMeBox").checked) {
		var mapCenter = map.getCenter();
		var cookieState = new Object();
	
		cookieState.lat = mapCenter.lat();
		cookieState.lng = mapCenter.lng();
		cookieState.zoom = map.getZoom();

		if (zipCode.value == zipCode.defaultValue) {
			cookieState.zip = "default";
		}
		else {
			cookieState.zip = zipCode.value;
		}
	
		cookieState.country_id = $(countrySelect).val();
		cookieState.mfg_id = $("#mfgSelector").val();
	
		cookieState.serv_id = new Array();
		$("input[name='serv_id']:checked").each(function() {
			cookieState.serv_id.push(this.value);
		});
	
		cookieState.prod_id = new Array();
		$("input[name='prod_id']:checked").each(function() {
			cookieState.prod_id.push(this.value);
		})
		
		cookieState.save = true;
		
		setCookie(cookieState);
	}
}

var SECONDS_IN_A_DAY = 86400;
function setCookie(obj) {
	date = new Date(new Date().getTime() + 60*SECONDS_IN_A_DAY);
	
	document.cookie = "find_merch" + "=" + escape($.toJSON(obj)) + "; expires=" + date.toGMTString();
}

// Retrieves the dealer locator cookie (find_merch) and converts it back to an object, which is then returned
function getCookie() {
	// cookies are separated by semicolons
	var aCookie = document.cookie.split("; ");
	for (var i=0; i < aCookie.length; i++)
	{
		// a name/value pair (a crumb) is separated by an equal sign
		var aCrumb = aCookie[i].split("=");
		if (aCrumb[0] == "find_merch") {
			return $.evalJSON(unescape(aCrumb[1]));
		}
	}

	// a cookie with the requested name does not exist
	return false;
}

function clearStateCookies() {
	setCookie({"save": false});
}
