//<![CDATA[
// created 2007/09/21, Yidao Cai
// last modified on 2009/10/08
// 2008/04/12: add popularity bars
// 2009/07/12: for wide area, jump to zoom 8-10 on click
// 2009/10/08: add searched area
var map;
var mapXmlDatafile = null; //"gardeninn.xml";
var gdir;
var geocoder = null;
var addressMarker;
var option_html = "";
var hotel_option_html = "";
var base_lat = 29.0;
var base_lng = -95.0;
var base_zoom = 10;
var url_hotel_search = "http://www.ynptravel.com/cgi-bin/hotel/ajsearch";
var action_type = "click";
var show_raw_xml = false;

// draw a highlighted circle at the current marker
var currentMarker = null;
var highlightCircle = null;

// keep a group of blue markers, usually fixed points of interests,
// always show them. These markers are from downloaded file.
var savedMarkers = new Array();
var numOfSavedMarkers = 0;

var iconBlue = new GIcon(); 
iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
iconBlue.iconSize = new GSize(12, 20);
iconBlue.shadowSize = new GSize(22, 20);
iconBlue.iconAnchor = new GPoint(6, 20);
iconBlue.infoWindowAnchor = new GPoint(5, 1);

// elabel
//          var label = new ELabel(marker.getLatLng(), '<div style="background-color:#ccccff;border:2px solid black;white-space:nowrap">'+title+'</div>', null, new GSize(3,-23), 75); 
//          map.addOverlay(label);
//          marker.Elabel = label; // === remember which Elabel beongs to this marker
// marker.Elabel.hide(); show();


    // Creates a "circle" using 20-sided GPolygon at the given point
    // Circle polygon object is global variable as there is only one highlighted marker at a time
    // and we want to remove the previously placed polygon before placing a new one.

var lastMousePoint = null;
var polyline = null; // for area searched

function highlightCurrentMarker()
{
    var markerPoint = currentMarker.getPoint();
    var polyPoints = Array();

    if (highlightCircle) {
        map.removeOverlay(highlightCircle);
    }

    var mapNormalProj = G_NORMAL_MAP.getProjection();
    var mapZoom = map.getZoom();
    var clickedPixel = mapNormalProj.fromLatLngToPixel(markerPoint, mapZoom);

    var polySmallRadius = 20;
    var polyNumSides = 20;
    var polySideLength = 18;

    for (var a = 0; a<(polyNumSides+1); a++) {
	var aRad = polySideLength*a*(Math.PI/180);
	var polyRadius = polySmallRadius; 
       	var pixelX = clickedPixel.x + polyRadius * Math.cos(aRad);
	var pixelY = clickedPixel.y + polyRadius * Math.sin(aRad);
	var polyPixel = new GPoint(pixelX,pixelY);
	var polyPoint = mapNormalProj.fromPixelToLatLng(polyPixel,mapZoom);
	polyPoints.push(polyPoint);
    }
    // Using GPolygon(points,  strokeColor?,  strokeWeight?,  strokeOpacity?,  fillColor?,  fillOpacity?)
    highlightCircle = new GPolygon(polyPoints,"#000000",2,0.0,"#0000FF",.5);
    map.addOverlay(highlightCircle);
}

function initialize(xmldatafile, actionType, baseLat, baseLng, baseZoom, showAtStart, showXml)
{
    initializeF(xmldatafile, actionType, baseLat, baseLng, baseZoom, showAtStart, showXml, "", "", "");

} 

// xmldatafile name without ".xml" extension
function initializeF(xmldatafile, actionType, baseLat, baseLng, baseZoom, showAtStart, showXml, hotelName, priceLow, priceHigh) 
{
    if (GBrowserIsCompatible()) 
    {
	mapXmlDatafile = xmldatafile + ".xml";
	base_lat = baseLat;
	base_lng = baseLng;
	base_zoom = baseZoom;
	action_type = actionType;
	show_raw_xml = showXml;

	map = new GMap2(document.getElementById("map"));
	//"mouseover" is the point where mouse entered the map!!!
	GEvent.addListener(map, "mousemove", 
		function (point) { lastMousePoint = point; });
	GEvent.addListener(map, "click", centerMapAndSetZoom);

	gdir = new GDirections(map, document.getElementById("directions"));
	GEvent.addListener(gdir, "load", onGDirectionsLoad);
	GEvent.addListener(gdir, "error", handleErrors);

	//load();
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
	map.addControl(new GScaleControl());
	map.addControl(new GOverviewMapControl());
	map.setCenter(new GLatLng(base_lat, base_lng), base_zoom);

	// Download data.xml and load it on the map. The format we expect is:
	// <markers>
	//   <marker lat="37.441" lng="-122.141"/>
	//   <marker lat="37.322" lng="-121.213"/>
	// </markers>
	// this is the initial data that will be show on map
	// later we can combine this with "stateChanged" action
	//hotel_option_html = "before download: " + mapXmlDatafile + "<p>\n";
	GDownloadUrl(mapXmlDatafile, function(data)
	{
	    var xml = GXml.parse(data);
	    processXml(xml, true);
	});

	// 2008/04/10: show hotels at init
	if (showAtStart) showHotelsOnMap("", "", "");
	if (showAtStart) showHotelsOnMap(hotelName, priceLow, priceHigh);
    }
}

function centerMapAndSetZoom()
{
    var clickPoint = lastMousePoint;
    if (clickPoint) {
	var userLat = clickPoint.lat().toFixed(6);
	var userLng = clickPoint.lng().toFixed(6);
	var currentZoom = map.getZoom();
	//alert("(" + userLat + ", " + userLng + "), zoom = " + currentZoom);
	var newZoom;
	if (currentZoom <= 1) newZoom = 4;
	else if (currentZoom <= 3) newZoom = currentZoom + 3;
	else if (currentZoom <= 6) newZoom = currentZoom + 2;
	else if (currentZoom <= 9) newZoom = 10;
	else if (currentZoom <= 11) newZoom = currentZoom + 1;
	else newZoom = currentZoom; // >=12: do not zoom by click, just center
	if (currentZoom < 14) map.setCenter(clickPoint, newZoom);
    }
}

function GetXmlHttpObject()
{ 
    var objXMLHttp=null;
    if (window.XMLHttpRequest) {
	objXMLHttp=new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
	objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    return objXMLHttp;
}

function showHotelsOnMap(hotelName, priceLow, priceHigh)
{
    xmlHttp = GetXmlHttpObject();
    if (xmlHttp == null) {
	alert ("Your browser does not support HTTP Request");
	return;
    } 

// call server to get data
    var url = url_hotel_search;
// we use '/' as "key=value" pair seperator, so it must be escaped.
// '=' should be safe because we only use the first one, like in
// key=somevalue=xyz
    var hotel_name = hotelName.replace(/\//g, "_slash_");
    //var center = map.getCenter();
    //var lat = center.lat(); //29.7;
    //var lng = center.lng(); //-95.4;
    //var distance = 20;
    var bounds = map.getBounds();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();
    var lat = southWest.lat();
    var lng = southWest.lng();
    var lat2 = northEast.lat();
    var lng2 = northEast.lng();

    var queryString = "/hotel_name=" + hotel_name
		+ "/price_low=" + priceLow
		+ "/price_high=" + priceHigh
		+ "/lat=" + lat
		+ "/lng=" + lng
		+ "/lat2=" + lat2
		+ "/lng2=" + lng2;
    url = url + queryString;

    // for debug only
    //document.getElementById("message_debug").innerHTML = url;

    xmlHttp.onreadystatechange = stateChanged;
    xmlHttp.open("GET", url, true);
    xmlHttp.send(null);
}

function stateChanged() 
{ 
    if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete")
    { 
	//document.getElementById("message").innerHTML=xmlHttp.responseText;
	map.clearOverlays();
	var xml = GXml.parse(xmlHttp.responseText);
	processXml(xml, false);
	if (numOfSavedMarkers > 0) {
	    for (var i = 0; i < numOfSavedMarkers; i++) {
		map.addOverlay(savedMarkers[i]);
	    }
	}
	showSearchedArea();
    }
    else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") { 
	document.getElementById("message").innerHTML =
		"<center><table width=450 height=80><tr><td bgcolor=\"#ffee00\" align=center><font color=\"#0033ff\"><b>Searching ... please wait a few seconds ...</b></font></td></tr></table></center>";
    } 
}

function showSearchedArea()
{
    var center = map.getCenter();
    var bounds = map.getBounds();
	  //var lngSpan = bounds.getNorthEast.lng() - bounds.getSouthWest.lng();
	  //var latSpan = bounds.getNorthEast.lat() - bounds.getSouthWest.lat();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();
	 var lngSpan = northEast.lng() - southWest.lng();
	  var latSpan = northEast.lat() - southWest.lat();
    var points = [];
    points.push(southWest);
    points.push(new GLatLng(southWest.lat(), northEast.lng()));
    points.push(northEast);
    points.push(new GLatLng(northEast.lat(), southWest.lng()));
    points.push(southWest);
    if (polyline) {
	map.removeOverlay(polyline);	// remove old line
    }
    polyline = new GPolyline(points, "#0033ff", 2, 0.8);
    map.addOverlay(polyline);
}
 
function processXml(xml, save_markers)
{
    if (show_raw_xml == true) {
	var hotel_xml = xml.replace(/</g, "&lt;");
	hotel_xml = hotel_xml.replace(/>/g, "&gt;");
	document.getElementById("hotel_xml").innerHTML = 
		"<font size=-2><pre>\n" + hotel_xml + "\n</pre></font>\n";
    }

    var markers = xml.documentElement.getElementsByTagName("marker");
    var warns = xml.documentElement.getElementsByTagName("warn"); //[0].firstChild.nodeValue;
    var sidebar = document.getElementById('hotel_options');
    sidebar.innerHTML = '';

    if (warns.length > 0) {
	var msg = ""; 
	for (var i = 0; i < warns.length; i++) {
		msg += warns[i].firstChild.nodeValue + "<br>\n";
	}
	document.getElementById("message").innerHTML = 
			'<span class="warn">' + msg + '</span>\n';
    }
    option_html = "";
    hotel_option_html = "";
    for (var i = 0; i < markers.length; i++)
    {
	var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
			parseFloat(markers[i].getAttribute("lng")));
	var text = markers[i].getAttribute("name");
	var url = markers[i].getAttribute("url");
	var desc = markers[i].getAttribute("desc");
	var popGrade = markers[i].getAttribute("popGrade");
	var msg = getPopGradeImageUrl(popGrade) 
			+ '<a href="' + url + '" target="ynphotel">' 
			+ text + '</a><br><font size=-1>'
			+ desc + '</font>';
	//document.getElementById("hotel_xml").innerHTML = 
		//"<font size=-2><pre>\n" + msg + "\n</pre></font>\n";
	//map.addOverlay(createMarker(point, action_type, msg, null));
	var marker = createMarker(point, action_type, msg, 
				save_markers? iconBlue : null);
	if (save_markers == true) {
		savedMarkers[numOfSavedMarkers++] = marker;
	}
	map.addOverlay(marker);

	var latlngStr = markers[i].getAttribute("lat") + "," +
	    			markers[i].getAttribute("lng");
	option_html += '<option value="' + latlngStr + '"';
	if (i == 0) {
		option_html += " selected";
	}
	option_html += ">" + text + "</option>\n";

	//hotel_option_html += '<a href="' + url + '" target="ynphotel">' 
		//	+ text + '</a><br><font size=-1>'
		//	+ desc + '</font><br>';
	var sidebarEntry = createSidebarEntry(marker, msg);
	sidebar.appendChild(sidebarEntry);
    }

    document.getElementById("dir_options").innerHTML = 
			"<select id=\"toAddress\" name=\"to\">"
			+ option_html
			+ "</select>";
    //document.getElementById("hotel_options").innerHTML = hotel_option_html;
}

function getPopGradeImageUrl(grade)
{
    if (grade == null || grade == '') {
	grade = 'X';
    }
    if (grade != 'A' && grade != 'B' && grade != 'C' && grade != 'D') {
	grade = 'X';
    }
    return '<img src="/logo/pop' + grade + '12x16.gif" width="16" height="12">';
}

function showDirection(addr1, addr2, locale, starting_point) 
{
    if (starting_point == 'A') {
	setDirections(addr1, addr2, locale);
    }
    else {
	setDirections(addr2, addr1, locale);
    }
}
   
function setDirections(addr1, addr2, locale) 
{
      //gdir.load("from: " + fromAddress + " to: " + "29.72, -95.388",
      gdir.load("from: " + addr1 + " to: " + addr2, { "locale": locale });
}

function handleErrors()
{
	   if (gdir.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: " + gdir.getStatus().code);
	   else if (gdir.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: " + gdir.getStatus().code);
	   
	   else if (gdir.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: " + gdir.getStatus().code);

	//   else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
	//     alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + gdir.getStatus().code);
	     
	   else if (gdir.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: " + gdir.getStatus().code);

	   else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
	     alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
	    
	   else alert("An unknown error occurred.");
}

function onGDirectionsLoad()
{ 
      // Use this function to access information about the latest load()
      // results.

      // e.g.
      // document.getElementById("getStatus").innerHTML = gdir.getStatus().code;
	  // and yada yada yada...
}

// Creates a marker with a info window
// action type: click, mouseover 
function createMarker(point, action, msg, icon)
{
    var marker;
    if (icon == null) {
	marker = new GMarker(point);
    }
    else {
	marker = new GMarker(point, icon);
    }
    if (action == "") action = "click";
    GEvent.addListener(marker, action, function() {
	marker.openInfoWindowHtml(msg);
    });
    return marker;
}

function createSidebarEntry(marker, html) {
    var div = document.createElement('div');
    div.innerHTML = html;
    div.style.cursor = 'pointer';
    div.style.marginBottom = '5px'; 
    GEvent.addDomListener(div, 'click', function() {
	//GEvent.trigger(marker, 'click');
	currentMarker = marker;
	highlightCurrentMarker();
    });

    GEvent.addDomListener(div, 'mouseover', function() {
	div.style.backgroundColor = '#eee';
	currentMarker = marker;
	highlightCurrentMarker();
    });

    GEvent.addDomListener(div, 'mouseout', function() {
	div.style.backgroundColor = '#dff';
    });
    return div;
}

//]]>
