var map;
var origin = null;
var destination;
var mainDirections = null;
var galleriesArray = new Array();
var tileLayers = [];
var tileDesignatorLayer = [];
var pageNumber = 0;
var origin = null;
var sortFunction = null;
var currentBox = null;
var initialSearch = null;  // this is used to make a distinction between the initial search and subsequent moves on the map
var visibleMarkerCount = 0;
var previousCenter = null;

var displayedGalleries = 0;
var galleriesPerPage = 3;
var mMgr;
var maxZoom = 5;
var minZoom = 13;

var space = ' ';
var numb = '0123456789';
var lwr = 'abcdefghijklmnopqrstuvwxyz';
var upr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

function isValid(parm,val) {

	try{
		if(parm == ""){
			return true;
		}
		for (i=0; i<parm.length; i++) {
			if (val.indexOf(parm.charAt(i),0) == -1){
				return false;
			}
		}
		return true;
	}catch(err){

		return false;
	}
	return false;
}

function isNumber(parm) {return isValid(parm,numb+space);}
function isLower(parm) {return isValid(parm,lwr+space);}
function isUpper(parm) {return isValid(parm,upr+space);}
function isAlpha(parm) {return isValid(parm,lwr+upr+space);}
function isAlphanum(parm) {return isValid(parm,lwr+upr+numb+space);} 
 
function isCanadian(zip) {
	
	if(isAlphanum(zip)){
		return true;
	}
	
	return false;
}

/// <summary>GoogleMapLoad is the onLoad event to start rendering the map to the googleMap div</summary>
///
/// <remarks></remarks>
function GoogleMapLoad() 
{
	if (google.maps.BrowserIsCompatible()){
		
	  	//
		//	Set the map to the US by default
		//		

		map = new google.maps.Map2($("#googleMap")[0]);
		map.setCenter(new google.maps.LatLng(Latitude, Longitude));
		map.setZoom(8);
		map.enableScrollWheelZoom();
		map.addControl(new GSmallMapControl());

		var mgrOptions = { borderPadding: 0 };
		mMgr = new MarkerManager(map, mgrOptions);
		
		//
		//	set a pointer to the move listener to null
		//
		
		map.listenerMoveEnd = null;

		//
		//	If a default address is passed in, have it go to it
		//
		
		if (defaultAddress != ''){
			var qs = new Querystring();
			if(qs.get("unserviced","") == "yes"){
				$("#notServiced")[0].style.display = 'block';
				setMetaInfo("3");
			}else{
				SetOrigin(defaultAddress);
				setMetaInfo("4");
			}
		}
	}
	
}

function setMetaInfo(value){
	//Adjust meta tags
	var metas = document.getElementsByTagName("meta");
	var x=0;
	for(x=0; x<metas.length; x++){
		if(metas[x].getAttribute("name") == "WT.si_x"){
			metas[x].setAttribute("content",value);
		}
		if(metas[x].getAttribute("name") == "WT.si_n"){
			metas[x].setAttribute("content","Extended Purchase");
		}
	}
}

/// <summary>handleMove kicks off the update process when the map is moved</summary>
///
/// <remarks></remarks>
function handleMove()
{

	if (map.getZoom() > minZoom || map.getZoom() < maxZoom){
		//
		//	Clear left panel
		//

		$('#noLocations')[0].style.display = 'block';
		$('#galleryContainer')[0].style.display = 'none';
		
	}else if (previousCenter.distanceFrom(map.getCenter()) > 2000){
		MapPoint(map.getCenter());
	}
	else{
		BindGalleries();
	}
	

}



/// <summary>name and description of function</summary>
///
/// <param name="paramname">description of parameter</param>
///
/// <remarks></remarks>
function handleErrors(){
	CloseDirections();
	
	if (mainDirections.getStatus().code == G_GEO_UNKNOWN_ADDRESS){
		alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + mainDirections.getStatus().code);
	}else if (mainDirections.getStatus().code == G_GEO_SERVER_ERROR){
		alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + mainDirections.getStatus().code);
	}else if (mainDirections.getStatus().code == G_GEO_MISSING_QUERY){
	     alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + mainDirections.getStatus().code)
	}else if (mainDirections.getStatus().code == G_GEO_BAD_KEY){
		     alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + mainDirections.getStatus().code);
	}else if (mainDirections.getStatus().code == G_GEO_BAD_REQUEST){
		alert("A directions request could not be successfully parsed.\n Error code: " + mainDirections.getStatus().code);
	}else{
		alert("An unknown error occurred.");
	}  
}

/// <summary>name and description of function</summary>
///
/// <param name="paramname">description of parameter</param>
///
/// <remarks></remarks>
function onmainDirectionsectionsLoad(){ 
    // Use this function to access information about the latest load()
    // results.

    // e.g.
    // $("#getStatus").innerHTML = mainDirections.getStatus().code;
	// and yada yada yada...
}

/// <summary>FormatPhoneNumber formats a string phone number to a pretty string</summary>
///
/// <param name="number">the string number that needs to beautified</param>
///
/// <remarks></remarks>
function FormatPhoneNumber(number)
{
	
	//
	//	strip out all formatting
	//
	
	number = number.replace(/\(/gi, '');
	number = number.replace(/\)/gi, '');
	number = number.replace(/ /gi, '');
	number = number.replace(/-/gi, '');
	
	//
	//	put in brackets and dash
	//
	
	if (number.length == 10)
	{	
		number = '(' + number;
		number = number.substr(0, 4) + ') ' + number.substr(4);
		number = number.substr(0, 9) + '-' + number.substr(9);
	}
	return number;
}

/// <summary>FormatZipCode formats a zip code to a pretty string</summary>
///
/// <param name="zip">the string number that needs to beautified</param>
///
/// <remarks></remarks>
function FormatZipCode(zip) {
    if (zip.length > 5 && !isCanadian(zip)) {
       return zip.substr(0, 5) + '-' + zip.substr(5);
   }
   return zip;
}
/// <summary>toRads converts a value to radians</summary>
///
/// <param name="val">the value to be converted</param>
///
/// <remarks></remarks>
function toRad(val)
{
  return val * Math.PI / 180;
}

/// <summary>HaversineFormula returns the distance in miles between two lat/long points</summary>
///
/// <param name="lat1">latitude of the first point</param>
/// <param name="lon1">longitude of the first point</param>
/// <param name="lat2">latitude of the second point</param>
/// <param name="lon2">longitude of the second point</param>
///
/// <remarks>returns the distance as an integer</remarks>
function HaversineFormula(lat1, lon1, lat2, lon2)
{
				
	var R = 3956;
	var dLat = toRad(lat2-lat1);
	var dLon = toRad(lon2-lon1); 
	var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
			Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
			Math.sin(dLon/2) * Math.sin(dLon/2); 
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
	var d = R * c;					
					
	return d;
}


/// <summary>SortByDistance is a sorting method to allow sorting by distance amongst the results</summary>
///
/// <param name="a">an object that contains the gallery distance from the origin</param>
/// <param name="b">an object that contains the gallery distance from the origin</param>
///
/// <remarks></remarks>
function SortByDistance(a, b)
{
	return a.distance-b.distance;
}

/// <summary>SortByService is a sorting method to allow sorting by gallery type</summary>
///
/// <param name="a">an object that contains the gallery type and distance from the origin</param>
/// <param name="b">an object that contains the gallery type and distance from the origin</param>
///
/// <remarks></remarks>
function SortByService(a, b)
{
	var num = 1;
	
	if (a.icon == 'furnitureGalleries' && b.icon != 'furnitureGalleries')
		num = -1;

	if (a.icon == 'comfortStudios' && b.icon != 'comfortStudios')
	{
		if (b.icon == 'furnitureGalleries')
			num = 1;
		else
			num = -1;
	}

	if (a.icon == b.icon)
	{
		num = a.distance - b.distance;
	}
	
	return num;
}

/// <summary>MapPoint retrieves the xml for the surrounding area</summary>
///
/// <param name="point">point on the map to retrieve addresses surrounding</param>
///
/// <remarks></remarks>
function MapPoint(point)
{

	previousCenter = point;
	
	if (!point)
	{
			$('#noLocations')[0].style.display = 'block';
			$('#galleryContainer')[0].style.display = 'none';
	} 
	else
	{
		
		//
		//	get gallery xml
		//
		
		var request = GXmlHttp.create();
		var params = "longitude=" + point.x + "&latitude=" + point.y;

		if ($("#rightOptin").length > 0 ){
			if(location.href.toLowerCase().indexOf("optindc") > -1){
				params += "&optindc=1";
			}else if(location.href.toLowerCase().indexOf("optin") > -1){
				params += "&optin=1";
			}
		}

		if (sitename != '') params += "&sitename=" + sitename;
		
		request.open("POST", applicationPath + "/XML/Galleries.aspx", true);
		request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		request.setRequestHeader("Content-length", params.length);

		request.onreadystatechange = function() 
		{
			if (request.readyState == 4) 
			{
				var xml = google.maps.Xml.parse(request.responseText);
				var docEl = xml.documentElement;
				var galleries = docEl.getElementsByTagName("row");

				for (var i = 0; i < galleries.length; i++)
				{
					var latitude = parseFloat(google.maps.Xml.value(galleries[i].attributes.getNamedItem("latitude")));
					var longitude = parseFloat(google.maps.Xml.value(galleries[i].attributes.getNamedItem("longitude")));
					var bizname = google.maps.Xml.value(galleries[i].attributes.getNamedItem("bizname"));
					var add1 = google.maps.Xml.value(galleries[i].attributes.getNamedItem("add1"));
					var city = google.maps.Xml.value(galleries[i].attributes.getNamedItem("city"));
					var state = google.maps.Xml.value(galleries[i].attributes.getNamedItem("state"));
					var zipcode = google.maps.Xml.value(galleries[i].attributes.getNamedItem("zip"));
					var icon = 'otherRetailers';
					var url = google.maps.Xml.value(galleries[i].attributes.getNamedItem("url"));
					var phone = google.maps.Xml.value(galleries[i].attributes.getNamedItem("phone"));
					
					var nfv5 = google.maps.Xml.value(galleries[i].attributes.getNamedItem("nfv5"));
					var nfv6 = google.maps.Xml.value(galleries[i].attributes.getNamedItem("nfv6"));

					if (nfv5 == '1'){
						icon = 'furnitureGalleries';
					}
					else if (nfv6 == '1'){
						icon = 'comfortStudios';
					}

					var latlng = new google.maps.LatLng(latitude, longitude);
					
					var directions = {};
					directions.latlng = latlng;
					directions.bizname = bizname;
					directions.add1 = add1;
					directions.city = city;
					directions.state = state;
					directions.zipcode = zipcode;
					directions.distance = Math.round(HaversineFormula(point.y, point.x, latitude, longitude));
					directions.icon = icon;
					directions.url = url;
					directions.phone = phone;
					directions.drawn = false;

					var existsAlready = false;
					
					jQuery.each(galleriesArray, function(){
	    				    //if ($.toJSON(directions.latlng) == $.toJSON(this.latlng)){
					        if (directions.latlng.x + '|' + directions.latlng.y == this.latlng.x + '|' + this.latlng.y)
					        {
    					        existsAlready = true;
								return false;
							}
						}
					);
					
					if (!existsAlready){
						//if (gallerytype == 'true' || gallerytype == 'gallery'){
							if (nfv5 == '1')
								galleriesArray.push(directions);
						//}else{
						//	galleriesArray.push(directions);
						//}
					}else{
						//
						//	Recalculate distance
						//						
					}
				}

				pageNumber = 0;
				
				//
				//	recalculate all the distances
				//
				
				for (var i = 0; i < galleriesArray.length; i++){
					galleriesArray[i].distance = Math.round(HaversineFormula(point.y, point.x, galleriesArray[i].latlng.lat(), galleriesArray[i].latlng.lng()));
				}
				
				//
				//	Focus on the closest location
				//

				if (galleriesArray.length > 0){
					galleriesArray.sort(SortByDistance); 

					if (initialSearch){
						map.setCenter(galleriesArray[0].latlng);
					}

					//
					//	if galleriesArray is longer than 50 then trim it
					//
					
					while (galleriesArray.length > 50)	{
						var disappearingGallery = galleriesArray.pop();

						if ($("#disappearingGallery.marker")[0].length){
							mMgr.removeMarker(disappearingGallery.marker);
						}
					}


					BindGalleries();

				}
				else{
					//
					//	Display the no locations message
					//
					
					if (initialSearch)
						map.setCenter(new google.maps.LatLng(38.95940879245423, -94.921875));
					
					$('#noLocations')[0].style.display = 'block';
					$('#galleryContainer')[0].style.display = 'none';
					
				}
				
				if (initialSearch){
					origin = point;
					map.listenerMoveEnd = google.maps.Event.addListener(map, "moveend", handleMove);
				}

				initialSearch = false;

			}
		}

		request.send(params);

	}
}

/// <summary>SetOrigin starts the process of mapping out from an origin based on an address</summary>
///
/// <param name="address">address to geocode to an origin and find locations from</param>
///
/// <remarks></remarks>
function SetOrigin(address)
{
    defaultAddress = address;
	initialSearch = true;
	if (map.listenerMoveEnd != null){
		google.maps.Event.removeListener(map.listenerMoveEnd);
	}

	sortFunction = SortByService;

	$('#noLocations')[0].style.display = 'none';
	$('#galleryContainer')[0].style.display = 'none';

	//map.clearOverlays();
	map.closeExtInfoWindow();
	mMgr.clearMarkers();
	
	
	galleriesArray = new Array();

	//$('#DealerLocator1_lblSearch')[0].innerHTML = address;

	var geocoder = new google.maps.ClientGeocoder();

	geocoder.getLatLng(
		address,
		MapPoint
	);
}

/// <summary>MarkerClick is the event that handles when a marker is clicked either by the left side list of galleries or the icon</summary>
///
/// <remarks></remarks>
function MarkerClick()
{
		
	try{
		map.setCenter(this.m.getLatLng());
	}catch(err){

	} 
}

/// <summary>BindGalleries binds the galleries in the galleriesArray to the left list (divGalleries)</summary>
///
/// <remarks></remarks>
function BindGalleries()
{	
	galleriesArray.sort(sortFunction); 

	//
	//	Generate left bar
	//

	var divGalleries = $('#divGalleries')[0];
	var previousPage = -1;
	var galleryPage = null;
	visibleMarkerCount = 0;

	divGalleries.innerHTML = "";
	
	displayedGalleries = 0;
	for (var i = 0; i < galleriesArray.length; i++)
	{

		var gallery = galleriesArray[i];
		var bounds = map.getBounds();
		
		if (bounds.contains(gallery.latlng))
		{
			
			displayedGalleries++;
			
			if (!gallery.drawn)
			{
				gallery.drawn = true;

				//
				//	Set up marker on map
				//

				var icon = new GIcon();
				icon.image = applicationPath + "/images/findADealer/marker_" + gallery.icon + ".png";
				icon.shadow = applicationPath + "/images/findADealer/marker_shadow.png";
				icon.iconSize = new GSize(29, 38);
				icon.shadowSize = new GSize(62, 43);
				icon.iconAnchor = new GPoint(13, 37);
				icon.infoWindowAnchor = new GPoint(14, 0);

				var marker = new google.maps.Marker(gallery.latlng, icon);
				marker.bizname = gallery.bizname;
				marker.add1 = gallery.add1;
				marker.city = gallery.city;
				marker.state = gallery.state;
				marker.zipcode = gallery.zipcode;
				marker.distance = gallery.distance;
				marker.latlng = gallery.latlng;
				marker.icon = gallery.icon;
				marker.index = i;
				marker.url = gallery.url;
				marker.phone = gallery.phone;

				marker.m = marker;

				gallery.marker = marker;

				google.maps.Event.addListener(marker, "click", MarkerClick);

				mMgr.addMarker(marker, 8, 12)

			}
			
			//
			//	if this gallery is within view, show it on the left nav
			//
		

			var galleryBox = document.createElement('a');
			//var galleryBox_icon = document.createElement('img');
			var galleryBox_text = document.createElement('div');
			var galleryBox_info = document.createElement('div');
			var galleryBox_spacer = document.createElement('div');

			galleryBox.id = 'galleryBox' + i;
			galleryBox.href = 'javascript:void(0);';

			if (currentBox == gallery.latlng.x + '|' + gallery.latlng.y/*$.toJSON(gallery.latlng)*/)
			{
				galleryBox.setAttribute("class", "galleryBox_selected");
				galleryBox.setAttribute("className", "galleryBox_selected");				
			}
			else if (visibleMarkerCount % 2 == 1)
			{
				galleryBox.setAttribute("class", "galleryBox_alternate");
				galleryBox.setAttribute("className", "galleryBox_alternate");
			}
			else
			{
				galleryBox.setAttribute("class", "galleryBox");
				galleryBox.setAttribute("className", "galleryBox");
			}

			galleryBox_spacer.setAttribute("class", "galleryBox_spacer");
			galleryBox_spacer.setAttribute("className", "galleryBox_spacer");
			galleryBox_spacer.innerHTML = '&nbsp;';

			//galleryBox_icon.setAttribute("class", "galleryBox_icon");
			//galleryBox_icon.setAttribute("className", "galleryBox_icon");
		
			//galleryBox_icon.style.border = '0px';
			//galleryBox_icon.src = "../images/findADealer/marker_" + gallery.icon + ".png";

			galleryBox_text.setAttribute("class", "galleryBox_text");
			galleryBox_text.setAttribute("className", "galleryBox_text");


			
			galleryBox_text.innerHTML = '<b>' + gallery.bizname + '</b><br/>' + 
										gallery.add1 + '<br/>' +
										gallery.city + ', ' + gallery.state + ' ' 
										+ FormatZipCode(gallery.zipcode)
										+ '<br/>'
										+ FormatPhoneNumber(gallery.phone);

			galleryBox_info.setAttribute("class", "galleryBox_info");
			galleryBox_info.setAttribute("className", "galleryBox_info");

			//galleryBox_info.innerHTML = 'Info';;

			galleryBox.appendChild(galleryBox_spacer);
			//galleryBox.appendChild(galleryBox_icon);
			galleryBox.appendChild(galleryBox_text);
			galleryBox.appendChild(galleryBox_info);

			//
			//	if new page, then add galleryBox to that new page
			//
			
			if (previousPage != Math.floor(visibleMarkerCount / galleriesPerPage)){

				previousPage = Math.floor(visibleMarkerCount / galleriesPerPage);
				galleryPage = document.createElement('div');
				galleryPage.id = 'galleryPage_' + previousPage;

				if (previousPage == 0)
					galleryPage.style.display = 'block';
				else
					galleryPage.style.display = 'none';
					
				divGalleries.appendChild(galleryPage);
				
			}


			//
			//	Set all my pointers to make life easy
			//

			gallery.marker.box = galleryBox;
			galleryBox.m = gallery.marker;
			galleryBox.onclick = function()	{ 
				google.maps.Event.trigger(this.m, "click");
			};

			galleryPage.appendChild(galleryBox);

			visibleMarkerCount++;

		}else{
			if ($("#gallery.marker").length){
			    if (currentBox == gallery.marker.getLatLng().x + '|' + gallery.marker.getLatLng().y/*$.toJSON(gallery.marker.getLatLng())*/)
			    {
					currentBox = null;
					map.closeExtInfoWindow()
				}
				mMgr.removeMarker(gallery.marker);
				gallery.drawn = false;
			}

		}	

	}

	UpdatePaging();
	
	$('#noLocations')[0].style.display = 'none';
	$('#galleryContainer')[0].style.display = 'block';


}

/// <summary>UpdatePaging updates the left side list based on the page number</summary>
///
/// <remarks></remarks>
function UpdatePaging()
{
	//
	//	update Paging
	//

	var pager = $('#galleryPagination')[0];

	var previousLink = null;
	var nextLink = null;
	var results = document.createElement('div');
	var divider = document.createElement('span');
	var leftArrow = document.createElement('span');
	var rightArrow = document.createElement('span');

	results.setAttribute("ID","PaginationResults");
	results.innerHTML = "Displaying Results " +
	(pageNumber * galleriesPerPage + 1) + "-" + ((pageNumber * galleriesPerPage + galleriesPerPage) > visibleMarkerCount ? visibleMarkerCount : (pageNumber * galleriesPerPage + galleriesPerPage)) + " of " + visibleMarkerCount;
	
	leftArrow.innerHTML = "&lt;&nbsp;";
	rightArrow.innerHTML = "&nbsp;&gt;";

	pager.innerHTML = "";
	divider.innerHTML = '&nbsp;|&nbsp;';

	pager.appendChild(leftArrow);

	//
	//	Make the previous link inactive if this is the first page
	//
	
	if (pageNumber == 0)
	{
		previousLink = document.createElement('span');
		previousLink.innerHTML = 'Prev';
	}
	else
	{
		previousLink = document.createElement('a');
		previousLink.href = 'javascript:void(0);';
		previousLink.innerHTML = 'Prev';
		previousLink.onclick = function(){FlipGalleriesPageBackward();};
	}

	//
	//	Make the next link inactive if this is the last page
	//

	if (pageNumber >= (Math.ceil(displayedGalleries / galleriesPerPage)) - 1 || displayedGalleries < galleriesPerPage)
	{
		nextLink = document.createElement('span');
		nextLink.innerHTML = 'Next';
	}
	else
	{
		nextLink = document.createElement('a');
		nextLink.href = 'javascript:void(0);';
		nextLink.innerHTML = 'Next';
		nextLink.onclick = function(){FlipGalleriesPageForward();};
	}

	//
	//	Add the objects to the pager div
	//
	
	pager.appendChild(results);
	pager.appendChild(leftArrow);
	pager.appendChild(previousLink);
	pager.appendChild(divider);
	pager.appendChild(nextLink);
	pager.appendChild(rightArrow);
}

/// <summary>FlipGalleriesPageForward moves the paging forward a page</summary>
///
/// <remarks></remarks>
function FlipGalleriesPageForward()
{
	//
	//	hide last page
	//
	
	var previousPage = $('#galleryPage_' + pageNumber)[0];
	previousPage.style.display = 'none';
	pageNumber++;
	var nextPage = $('#galleryPage_' + pageNumber)[0];
	nextPage.style.display = 'block';
	UpdatePaging();
	
}

/// <summary>FlipGalleriesPageBackward moves the paging back a page</summary>
///
/// <remarks></remarks>
function FlipGalleriesPageBackward()
{
	var previousPage = $('#galleryPage_' + pageNumber)[0];
	previousPage.style.display = 'none';
	pageNumber--;
	var nextPage = $('#galleryPage_' + pageNumber)[0];
	nextPage.style.display = 'block';
	UpdatePaging();

}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

//
//	Add the google rendering function to the page load
//

addLoadEvent(GoogleMapLoad);