/// Quick Fix
if(!this.core_url) {
	core_url = "http://www.monroecounty.gov/modules/mc_modules/core";
}

/// Configurables

// icon definitions

var YMAP_ICON_911 = 			{src: core_url +"/i/mapicons/911-incident-icon.gif", 		w:15, h:15 };
var YMAP_ICON_INCIDENT_1 =		{src: core_url +"/i/mapicons/incident-yellow.gif", 			w:15, h:15 };
var YMAP_ICON_INCIDENT_2 =		{src: core_url +"/i/mapicons/incident-orange.gif", 			w:15, h:15 };
var YMAP_ICON_INCIDENT_3 =		{src: core_url +"/i/mapicons/incident-red.gif", 			w:15, h:15 };
var YMAP_ICON_CONSTRUCTION =	{src: core_url +"/i/mapicons/roadwork.gif", 				w:15, h:15 };
var YMAP_ICON_SEX_OFFENDER =	{src: core_url +"/i/mapicons/sex-offender-icon.gif", 		w:15, h:15 };
var YMAP_ICON_SEX_OFFENDERS = 	{src: core_url +"/i/mapicons/sex-offender-multiples.gif", 	w:20, h:20 };
var YMAP_ICON_PARK =		 	{src: core_url +"/i/mapicons/park.gif"					, 	w:15, h:15 };
var YMAP_ICON_PARK_SELECTED =	{src: core_url +"/i/mapicons/park-selected.gif",		 	w:15, h:15 };

/// urls

var ymapFetchOffendersURL = 	window.core_url + "/ymap/ymap.php?task=offender";
var ymapLocationSearchURL = 	window.core_url + "/ymap/ymap.php?task=location";

/// initial map positions

var ymapInitialLatitude = 		43.155853;
var ymapInitialLongitude = 		-77.608546;
var ymapInitialScale = 			8;
var ymapTinyInitialScale = 		8;
var ymapParksInitialScale = 	9;

/// template bindings

var ymapMapDivID =				"ymap";
var ymapTinyMapID = 			"ymap-tiny";
var ymapItemDivIDPrefix = 		"ymap-item-";	
var ymapHighlightClass = 		"ymap-highlight";

/// yahoomap constructor. 
function ymap() {}

/// Defers map drawing until agreement is pressed.
ymap.prototype.waitForAgreement = function() {
	var instance = this;
	e("ymap-confirm-button").onclick = function() {
		/// Strip ymap of it's class.
		e("ymap").className = "";
	
		/// Hide agreement, draw map and load the offenders via ajax.
		e("ymap-disclaimer").className = "disHide";
		instance.drawMap();
		instance.loadOffenders();
		
		/// Hide agreement button, show search form
		add(e("ymap-confirm"), "disHide");
		rem(e("ymap-search"), "disHide");
		
		/// Labels for "street", "city" and "zip" are displayed right in the
		/// input field.
		instance.inputStreet = e("ymap-search-street");
		instance.inputCity = e("ymap-search-city");
		instance.inputZip = e("ymap-search-zip")
		helpText(instance.inputStreet, "street");
		helpText(instance.inputCity, "city");
		helpText(instance.inputZip, "zip");
		
		/// Wire the "go" button to the location search.
		var this_onLocationSearch = function() { instance.onLocationSearch() };
		e("ymap-search-submit").onclick = this_onLocationSearch;
	}
}

/// Defers map drawing until the panel has been opened. Panel is the accordion
/// object containing the map, lists is the accordion object containing the
/// incident lists. Struct should be an array of arrays with values for: lat,
/// long, image (one of the objects defined above), div (id of info div), panel#
/// (panel the info div belongs to). For info divs with no location, just the
/// panel is specified (instead of the array).
ymap.prototype.waitForOpenBlockPanel = function(panel, lists, struct) {
	var instance = this;
	this.listPanels = lists;
	this.mapPanel = panel;
	this.markerData = struct;
	this.mapLoaded = false;
	this.highlightedInfo = false;
	
	/// When map panel is opened obviously the map needs to be loaded.
	/// this.mapPanel.panelOpenCallback = function() { instance.requireLoadedOpenMap(); }
	
	
	/// Wire up the descriptions so they open the map panel.
	var makef = function(j) { return function() {
		if(instance.slaveMap) {
			instance.slaveMap.goToMarker(j);
		}
		else {
			instance.pendingMarker = j;
			///instance.requireLoadedOpenMap();
			map_acc.extLoad(map_acc.url, true);
		}
	}}
	var markerDiv;
	for(i in this.markerData) {
		if(this.markerData[i].lat && this.markerData[i].lon) {
			markerDiv = e(ymapItemDivIDPrefix + this.markerData[i].div);
			markerDiv.onclick = makef(i);
		}
	}
}

///
ymap.prototype.initializeIframeMap = function() {
	this.controllerMap = window.parent.ymapInstance;
	
	this.scale = ymapTinyInitialScale;
	
	/// Create a lat/lon object
	var monroe = new YGeoPoint(ymapInitialLatitude, ymapInitialLongitude);
	
	this.map = new YMap(e('ymap'));
	
	this.map.drawZoomAndCenter(monroe, this.scale);
	
	this.markerData = this.controllerMap.markerData;
	
	/// Put all the stored markers in the map.
	var i;
	var mark;
	var data; 
	/// makes callback functions
	var instance = this;
	var makef = function(j) { return function() {
		instance.goToMarker(j);
	}}
	for(i in this.markerData) {
		data = this.markerData[i];
		
		/// Add marker to map, only if it has location information.
		if(data.lon && data.lat)  {
			mark = this.addMarker(data.lat, data.lon, data.img);
		
			/// Wire up click callback.
			YEvent.Capture(mark, EventsList.MouseClick, makef(i));
		}
	}
	
	this.controllerMap.slaveMap = this;
	
	if(this.controllerMap.pendingMarker) {
		this.goToMarker(this.controllerMap.pendingMarker);
	}
	
	add(e("ymap-scale-" + this.scale), "highlight");
	makef = function(j) { return function() { instance.setScale(j); }}
	for(i = 1; i <= 16; i++) {
		e("ymap-scale-" + i).onclick = makef(i);
	}
	e("ymap-zoom-in").onclick = function() { instance.incScale(); }
	e("ymap-zoom-out").onclick = function() { instance.decScale(); }
}

/// Loads the yahoo javascript and creates the map.
ymap.prototype.requireLoadedOpenMap = function() {
	if(!this.mapLoaded) {
		var instance = this;
		
		/// Make the browser load the Yahoo ajax api.
		///var this_iframeCallback = function(map){ instance.iframeCallback(map); }
		///includejs(ymapYahooJavascriptURL, this_iframeCallback);
		
		var container = e("ymap-tiny");
		
		container.innerHTML = '<iframe id="ymap-iframe" src="/widgets2/ymap.php?task=iframe"></iframe>';
		
		/// don't do this function ever again.
		this.mapPanel.panelOpenCallback = function(){};
	
		this.mapLoaded = true;
	}
	if(this.mapPanel.open == -1) this.mapPanel.panels[0].open();
}

/// Centers the marker indexed by index in markerData, and highlights the info
/// div
ymap.prototype.goToMarker = function(index) {
	var point = new YGeoPoint(this.markerData[index].lat, this.markerData[index].lon);
	this.map.panToLatLon(point);
	this.highlightInfoAtIndex(index);
}

/// unhighlight an info div by removing the highlight class
ymap.prototype.unhighlightInfo = function() {
	if(this.highlightedInfo) {
		rem(this.highlightedInfo, ymapHighlightClass);
		this.highlightedInfo = false;
	}
}

/// highlight an info div by adding the highlight class
ymap.prototype.highlightInfoAtIndex = function(i) {
	this.unhighlightInfo();
	
	var div = window.parent.e(ymapItemDivIDPrefix + this.markerData[i].div);
	add(div, ymapHighlightClass);
	this.highlightedInfo = div;
	
	/// Also gotta make sure the right panel is open.
	/// this.controllerMap.listPanels.panels[this.markerData[i].pan].makeOpenIfNot();
	var pan = this.markerData[i].pan;
	var inc_acc = parent.inc_acc;
	if(inc_acc.i != this.markerData[i].pan) inc_acc.links[pan].onclick();
	var pnl = window.parent.e("ymap-panel-" + pan);
	
	/// Also gotta scroll to it.
	var scrollTop = 0;
	while(div = div.previousSibling) {
		if(div.offsetHeight) scrollTop += parseInt(div.offsetHeight);
	}
	pnl.scrollTop = scrollTop;
}

/// Load offenders, ajax style.
ymap.prototype.loadOffenders = function() {
	/// a for Ajax.
	var a = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
	a.open("get", ymapFetchOffendersURL);
	
	var instance = this;
	a.onreadystatechange = function() {
		if(a.readyState == 4) { ///< Request complete. 
			if(a.status == 200) { ///< Request successfull. 
				instance.parseOffenderDOM(a.responseXML);
			}
			else alert("error retrieving offender xml.");
		}
	}
	a.send('');
}

/// parse the DOM and turn it into offender markers.
ymap.prototype.parseOffenderDOM = function(dom) {
	/// n for nodes.
	var n = dom.firstChild.childNodes;
	
	for(i = 0; i < n.length; i++) {
		this.addMarkerWithText(	parseFloat(n[i].getAttribute("latitude")), 
								parseFloat(n[i].getAttribute("longitude")),
								eval( n[i].getAttribute("image") ),
								n[i].firstChild.nodeValue);
	}
}

/// Query Yahoo for the latitude and longitude of an address via ajax.
ymap.prototype.onLocationSearch = function() {
	if(!this.ajax) this.ajax = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
	if(this.ajax.readyState) this.ajax.abort();
	
	this.ajax.open("get", ymapLocationSearchURL + "&street=" + this.inputStreet.value + "&zip=" + this.inputZip.value + "&city=" + this.inputCity.value + "&state=NY");
	
	var instance = this;
	this.ajax.onreadystatechange = function() {
		if(instance.ajax.readyState == 4) { ///< Request complete. 
			if(instance.ajax.status == 200) { ///< Request successfull. 
				instance.parseLocationDOM(instance.ajax.responseXML);
			}
			else alert("error retrieving search xml.");
		}
	}
	this.ajax.send('');
}

/// parse the yahoo location DOM and center the map on the result.
ymap.prototype.parseLocationDOM = function(dom) {	
	var latNode = dom.getElementsByTagName("Latitude");
	var lonNode = dom.getElementsByTagName("Longitude");
	
	/// If both nodes are present then it's a valid response.
	if(latNode.length & lonNode.length) {
		var address = dom.getElementsByTagName("Address")[0].firstChild.nodeValue;
		var city = dom.getElementsByTagName("City")[0].firstChild.nodeValue;
		var state = dom.getElementsByTagName("State")[0].firstChild.nodeValue;
		var zip = dom.getElementsByTagName("Zip")[0].firstChild.nodeValue;
		
		/// Make the location object.
		var loc = new YGeoPoint(parseFloat(latNode[0].firstChild.nodeValue), parseFloat(lonNode[0].firstChild.nodeValue));
		
		/// Create the new marker.
		var mark = new YMarker(loc);
		mark.addLabel("*");
		
		/// Setup the onclick callback that opens the "smart window"
		var openSmartWindow = function() { mark.openSmartWindow("<p>" + address + "</p><p>" + city + ", " + state + " " + zip + "<p>"); }
		YEvent.Capture(mark, EventsList.MouseClick, openSmartWindow);
		
		/// Add marker to map.
		this.map.addOverlay(mark);
		this.map.drawZoomAndCenter(loc, 2);
	}
	else alert("location not found");
}

/// Initialize and display the Yahoo map.
ymap.prototype.drawMap = function() {
	this.scale = ymapInitialScale;
	
	/// Create a lat/lon object
	var monroe = new YGeoPoint(ymapInitialLatitude, ymapInitialLongitude);
 	
 	/// Create a map object
 	this.map = new  YMap(e(ymapMapDivID));
 	
 	/// Add controls.
  	this.map.addZoomShort();
 	this.map.addPanControl();
 		
 	/// TO DO: implement a safari fix so it doesn't crash.
 	if(navigator.userAgent.indexOf("Safari") == -1)	{}
 	
 	/// Display the map centered on a latitude and longitude
  	this.map.drawZoomAndCenter(monroe, this.scale);
}

/// Pulls text out of a container div then forwards all the parameters to
/// addMarker.
ymap.prototype.addMarkerByDivId = function(latitude, longitude, image, textid, open) {
	this.addMarkerWithText(latitude, longitude, image, e(textid).innerHTML, open);
}

/// Add a marker with a label and text to the Yahoo map. image should be one
/// of the preset variables above
ymap.prototype.addMarkerWithText = function(latitude, longitude, image, text, open) {
	var mark = this.addMarker(latitude, longitude, image);
	var loc = new YGeoPoint(latitude, longitude);
	
	/// Simple callback function to open a "smart window."
	var instance = this;
	openMarker = function() { instance.map.panToLatLon(loc); mark.openSmartWindow(text); }
	YEvent.Capture(mark, EventsList.MouseClick, openMarker);
	
	if(open) setTimeout(openMarker, 1000);
}

/// Low level (no text) marker adding. Image should be one of the image objects
/// configured above. Returns the marker.
ymap.prototype.addMarker = function(latitude, longitude, image) {
	/// Set up the image.
	var icon = new YImage();
	icon.size = new YSize(image.w, image.h);
	icon.src = image.src;
	icon.offsetSmartWindow = new YCoordPoint(7, 7);
	
	// Set up the location.
	var loc = new YGeoPoint(latitude, longitude);
	
	/// Mark it.
	var mark = new YMarker(loc, icon);
	this.map.addOverlay(mark);
	
	return mark;
}

ymap.prototype.setScale = function(scale) {
	/// unhighlight old scale
	rem(e("ymap-scale-" + this.scale), "highlight");
	
	/// highlight new scale
	add(e("ymap-scale-" + scale), "highlight");
		
	this.scale = scale;
	this.map.setZoomLevel(scale);
}

ymap.prototype.initParkMap = function(park_data) {
	var instance = this;
	var monroe = new YGeoPoint(ymapInitialLatitude, ymapInitialLongitude);
	
	this.map = new YMap(e('ymap-tiny'), null, new YSize(198, 217));
	this.scale = ymapParksInitialScale;
	this.map.drawZoomAndCenter(monroe, this.scale);
	
	/// Get rid of the scale - it looks real bad with this small of a map.
	e('ymap-tiny').removeChild(e('ymap-tiny').childNodes[2]);
	
	this.map.addZoomShort();
	
	var i = YMAP_ICON_PARK;
	var icon = new YImage();
	icon.size = new YSize(i.w, i.h);
	icon.src = i.src;
	icon.offsetSmartWindow = new YCoordPoint(7,7);
	
	/// TO DO: figure out how to swap images for markers already plotted (could just make a new marker) to show the 'selected' icon.
	
	var s = YMAP_ICON_PARK_SELECTED;
	var icon_s = new YImage();
	icon_s.size = new YSize(s.w, s.h);
	icon_s.src = s.src;
	icon_s.offsetSmartWindow = new YCoordPoint(7,7);
	
	var last_activated = null;
	var last_activated_mark = null;
	
	var activate_marker = function(mark, info, address) {
		var scrollTop = 0;
		var div = info;
		while(div = div.previousSibling) {
			if(div.offsetHeight) scrollTop += parseInt(div.offsetHeight);
		}
		e('parks').scrollTop = scrollTop;
		
		if(last_activated) {
			rem(last_activated, 'ymap-highlight');
			last_activated_mark.changeImage(icon);
		}
		add(info, 'ymap-highlight');
		last_activated = info;
		last_activated_mark = mark;
		
		mark.changeImage(icon_s);
		
		instance.map.panToLatLon(mark.YGeoPoint);
	}
	
	var make_marker = function(id, address) {
		var mark = new YMarker(address, icon);
		instance.map.addOverlay(mark); 
		var info = e('park-'+ id)
		
		var mark_onclick = function() {
			activate_marker(mark, info, address);
		}
		YEvent.Capture(mark, EventsList.MouseClick, mark_onclick);
		info.onclick = function() {
			activate_marker(mark, info, address);
		}
	}
	
	var j;
	for(j in park_data) {
		make_marker(j, park_data[j]);
	}
}

ymap.prototype.decScale = function(){if(this.scale < 16) this.setScale(this.scale + 1);}
ymap.prototype.incScale = function() {if(this.scale > 1) this.setScale(this.scale - 1);}