/**
*	SearchClient handles populating search results and sending asynchronous
*	search requests to the server.
*
*	Uses HTML tags with the following IDs:
*		searchmap -		the div to contain the map
*		resList	-		the TBODY tag to hold the search results list
*		resNav -		the container to hold the list of result pages
**/

function SearchClient()
{
	this.mapDiv = null;
	this.map = null;
	this.points = new Array();
	this.skipAMove = false;
}

SearchClient.ENONE = 0;
SearchClient.ECRIT = 1;
SearchClient.EWARN = 2;
SearchClient.EINFO = 3;
SearchClient.EDBUG = 4;
SearchClient.LOG_LEVEL = SearchClient.EDBUG;
SearchClient.MAP_LAT = 43.06976;
SearchClient.MAP_LONG = -89.25293;
SearchClient.MAP_ZOOM = 7;
SearchClient.SERVER_URL = "mapserver.php";
SearchClient.instance = null;

SearchClient.printLog = function(msg, type)
{
	if (SearchClient.LOG_LEVEL >= type)
		alert(msg);
}

SearchClient.prototype.addPoint = function(lat, lng, type, id, bubble)
{
	var point = new GMarker(new GLatLng(lat, lng));
	point.mlsID = id;
	point.bindInfoWindowHtml(bubble);

	this.map.addOverlay(point);
	this.points.push(point);
}

SearchClient.prototype.clearPoints = function()
{
	for (var index in this.points)
	{
		this.map.removeOverlay(this.points[index]);
	}
	this.points = new Array();
}

SearchClient.prototype.initialize = function(minlat, maxlat, minlong, maxlong, zoom, mapType)
{
	this.mapDiv = document.getElementById("searchmap");

	if (this.mapDiv)
	{
		if (GBrowserIsCompatible())
		{
			this.map = new GMap2(this.mapDiv);
			
			var mapTypes = {
				"normal": G_NORMAL_MAP, 
				"satellite": G_SATELLITE_MAP, 
				"hybrid": G_HYBRID_MAP
			};
			
			this.latitude = (minlat + maxlat) / 2;
			this.longitude = (minlong + maxlong) / 2;
			this.zoom = zoom;
			this.mapType = mapTypes[mapType];
			this.map.setCenter(new GLatLng(this.latitude, this.longitude), this.zoom, this.mapType);
			var zoomval = this.map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(minlat, minlong), new GLatLng(maxlat, maxlong)));

			if (this.zoom != zoomval)
			{
				this.zoom = zoomval;
				this.map.setZoom(zoomval);
			}

			try
			{
				this.map.addControl(new GLargeMapControl());
				this.map.addControl(new GMapTypeControl());
				this.map.enableDragging();
				this.map.enableDoubleClickZoom();
				this.map.enableContinuousZoom();
				this.map.enableScrollWheelZoom();
				
				var me = this;
				GEvent.addListener(this.map, "click", function (overlay, point) { return me.onMapClick(overlay, point); });
				GEvent.addListener(this.map, "moveend", function () { return me.onMapMove(); });
				GEvent.addListener(this.map, "maptypechanged", function () { return me.onMapTypeChange(); });
			}
			catch (error)
			{
				SearchClient.printLog(error.message, SearchClient.ECRIT);
			}
		}
		else
		{
			SearchClient.printLog("This web browser is incompatible with the mapping service.", SearchClient.ECRIT);
		}
	}
}

SearchClient.prototype.destroy = function()
{
	GUnload();
}

SearchClient.prototype.onMapClick = function(overlay, point)
{
	if (overlay != null && overlay.mlsID > 0)
	{
		this.skipAMove = true;
	}
}

SearchClient.prototype.onMapMove = function()
{
    if (this.skipAMove)
    {
		this.skipAMove = false;
    }
	else
	{
		var state = this.getState();
		state["action"] = "list";
    
		this.makeRequest(state);
	}
}

SearchClient.prototype.onMapTypeChange = function()
{
    var state = this.getState();
    state["action"] = "type";
    
    this.makeRequest(state);
}

SearchClient.prototype.getState = function()
{
    var bounds = this.map.getBounds();
    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();
    
    var returnVal = new Array();
    returnVal["minlat"] = sw.lat();
    returnVal["maxlat"] = ne.lat();
    returnVal["minlong"] = sw.lng();
    returnVal["maxlong"] = ne.lng();
    returnVal["zoom"] = this.map.getZoom();
    
    switch (this.map.getCurrentMapType())
    {
        case G_NORMAL_MAP:
                returnVal["maptype"] = "normal";
                break;
        case G_SATELLITE_MAP:
                returnVal["maptype"] = "satellite";
                break;
        case G_HYBRID_MAP:
                returnVal["maptype"] = "hybrid";
                break;
        default:
                break;
    }
    
    return returnVal;
}

SearchClient.prototype.makeRequest = function(hash)
{
	var me = this;
        var url = SearchClient.SERVER_URL + "?";
        var args = new Array();
        
        for (var key in hash)
        {
            args.push(key + "=" + hash[key]);
        }
        
        url += args.join("&");
        
	GXmlHttp.request(url, "", function(text){me.onReply(text);});
}

SearchClient.prototype.onReply = function(text)
{
	var reply = eval("(" + text + ")");

	if (reply.response)
	{
		switch (reply.response)
		{
			case "error":
				SearchClient.printLog(reply.errors.join("\n"), SearchClient.ECRIT);
				break;
			case "list":
				this.clearPoints();
				var nav = document.getElementById("resNav");
				var lst = document.getElementById("resList");

				if (reply.points)
				{
					for (var i = 0; i < reply.points.length; i++)
					{
						this.addPoint(reply.points[i].lat, reply.points[i].lng, 0, reply.points[i].mls, reply.points[i].bubble);
					}
					nav.innerHTML = reply.nav;
					lst.innerHTML = reply.list;
				}
				else
				{
					nav.innerHTML = "";
					lst.innerHTML = "";
				}
				break;
			case "bubble":
				this.map.updateInfoWindow("testing");
				break;
			case "ok":
				break;
			default:
				SearchClient.printLog("Got a weird response: " + reply.response, SearchClient.EWARN);
				break;
		}
	}
	else
	{
		SearchClient.printLog("AJAX reply did not contain a response attribute", SearchClient.EWARN);
	}
}


/**
* Google API Customization
**/

GMarker.prototype.mlsID = 0;

GXmlHttp.request = function(url, data, callback)
{
	var sock = GXmlHttp.create();
	sock.onreadystatechange = function() { GXmlHttp.onRecv(sock, callback); };
	sock.open("POST", url, true);
	sock.send(data);
}

GXmlHttp.onRecv = function(socket, callback)
{
	if (socket.readyState == 4)
	{
		callback(socket.responseText);
	}
}
