/*
 * Copyright 2006, Jeffrey Palm.
 */

var Jeff = {
  Version: '1.1. 2',
  prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
};
	
if ((typeof Prototype=='undefined') || Jeff.prototypeVersion < 1.3)
	throw("Jeff requires the Prototype JavaScript framework >= 1.3");

// Check the browser
var BROWSER;
if (document.all) {
	BROWSER = "IE";
 } else {
	BROWSER = "OTHER";
 }



/**
 * This is the main object.  It provides methods for drawing on
 * the screen, etc.
 */
Jeff.API = Class.create();
Jeff.API.prototype = {

	initialize: function(){
		//this.pane = new Pane('canvas');
		this.map = 0;
		//
		// these are set in main
		//
		this.tree = 0;
		this.main = 0;
		this.accordion = 0;

		this.models = new Array();

	},

	load: function() {
		//this.pane.showContent('canvas','',function(){});
	},

	onBodyLoad: function() {
		/*		this.accordion = new Rico.Accordion( $('accordionDiv'), 
																				 {panelHeight:404, 
																						 panelWidth: 600, 
																						 borderColor: '#000000'
																						 } );
		*/
		//this.map = new Jeff.Map(this);
		//this.accordion.showTabByIndex(1,true);

	},
	
	showMessage: function(msg, opts) {
		var e = $('messages');
		e.style.color = 'black';
		e.innerHTML = msg;
	},

	showError: function(msg, opts) {
		var e = $('messages');
		e.style.color = 'red';
		e.innerHTML = msg;
	},

	addModel: function(node) {
		this.tree.addNode(node);
		this.models.push(node);
	},

	/**
	 * (DOMElement | String)[html] (String[key] -> String[val]) -> _
	 * @interface
	 */
	showMainHTML: function(html, opts) {
		//this.pane.showContent('canvas',html,function(){});		

		var n = $('canvascontainer');
		n.style.textAlign = 'left';

		if (typeof html == 'string') {
			n.innerHTML = html;
		} else {
			//
			// remove all the nodes and ad html
			//
			if (n.childNodes) {
				while (n.childNodes && n.childNodes.length>0) {
					n.removeChild(n.childNodes[0]);
				}
			}
			n.appendChild(html);
			if (BROWSER == "IE") {
				var newHTML = n.innerHTML;
				n.innerHTML = newHTML;
			}
		}
	},

	getMap: function() {
		return this.map;
	},

	getPrevNode: function(node) {
		return this.tree.getPrevSibling(node);
	},

	getNextNode: function(node) {
		return this.tree.getNextSibling(node);
	},

	showOnCanvas: function(node) {
		if (node.getMainHTML) {
			var msg = 'loading <em>' + node.toString() + '</em>...';
			try {
				var thiz = this;
				node.getMainHTML(this, function(html) {
													 thiz.showMessage(msg);
													 thiz.showMainHTML(html);
													 thiz.showMessage(msg + 'done.');
													 //
													 // now show the accordion
													 //
													 //thiz.accordion.showTabByIndex(1,true);

													 //
													 // update the prev and next siblings
													 //
													 //todo var nextSibling = thiz.tree.getNextSibling(node);
													 //todo var prevSibling = thiz.tree.getPrevSibling(node);
												 });
			} catch (e) {
				
				this.showMessage(msg + 'done with errors: ' + e);
				//todo: untoggle
			}
		}
	},

	showOnMap: function(node,showNow) {
		if (this.getMap()) {
					if (node.getPoint && node.getMapHTML) {
						var msg = 'geocoding <em>' + node.toString() + '</em>...';
						this.showMessage(msg);
						//todo this.tree.toggle();
						try {
							var thiz = this;
							node.getPoint(thiz, function(p) {
															var fHtml = function(callback) {
																node.getMapHTML(thiz, function(html) {
																									callback(html);
																									thiz.showMessage(msg + 'done.');
																									//thiz.accordion.showTabByIndex(0,true);
																								});
															};
															thiz.getMap().showPoint(p,fHtml,showNow,node);
														});
							
						} catch (e) {
							thiz.showMessage(msg + 'done with errors: ' + e);
							//todountoggle();
						}
					}
		}
	},

	// GPoint
	mapClick: function(point) {

		var lon = point.x;
		var lat = point.y;

		var jeffPoint = new Jeff.Point(lon,lat);

		var thiz = this;

		var url = '/cgi-bin/zipcodes/index.pl';
		var params = 'lon=' + lon + '&lat=' + lat;
		var callback = function(res) {
			if (!res) return;
			var doc = res.responseXML.documentElement;

			var info = getElementByTagName(doc,'info');
			var city = info.getAttribute('city');
			var state = info.getAttribute('state');

			var loc = city;

			var first = true;
			for (var i=0; i<thiz.models.length; i++) {
				var model = thiz.models[i];
				if (model.getNodesForLocation) {
					thiz.showMessage('showing <em>' + model + '</em> @ ' + loc);
					model.getNodesForLocation(thiz, loc, jeffPoint, function (nodes) {
																			if (first) {
																				thiz.getMap().centerAndZoom(lon,lat,8);
																				first = false;
																			}
																			if (nodes) {
																				$A(nodes).each(function(node) {
																												 thiz.showOnMap(node,false);
																											 });
																			}

																	 });
				}
			}
		};
		new Ajax.Request (url,
											{   method: 'get', 
													parameters: params, 
													onSuccess: callback
													});		
	},

	_dummy: function() {}

};

Jeff.Map = Class.create();
Jeff.Map.prototype = {
	
	initialize: function(api) {
		this.api = api;
		var m = new GMap($("mapContent"));
		m.addControl(new GLargeMapControl());
		m.addControl(new GMapTypeControl());
		m.addControl(new GScaleControl());
		
		m.centerAndZoom(new GPoint(-94.926791,36.863917), 13);

		this.map = m;

		this.nodes2markers = new Array();

		var thiz = this;
		GEvent.addListener(this.map, "click", function (overlay,point) {
												 if (!overlay && point) {
													 thiz.api.mapClick(point);
												 }
											 });

	},

	centerAndZoom: function(lon,lat,zoom) {
		this.map.centerAndZoom(new GPoint(lon,lat),zoom);
	},

	_htmlStartDOM: function() {
		var div = $n('div');
		div.style.padding = "2px";
		div.style.whiteSpace = "nowrap";
		div.style.minWidth = "300px";
		div.style.maxWidth = "400px";
		return div;
	},
	
	_htmlStart: function() {
		var s = "<div style=\"padding: 2px; white-space: nowrap; ";
		s += "min-width: 350px";
		s += "\">";
		return s;
	},

	_htmlEnd: function() {
		return "</div>";
	},

	/**
	 * Jeff.Ppoint (DOMElement | String)[html] Object Boolean -> _
	 * @interface
	 */
	showPoint: function(point, fHtml,showNow,forWhom) {
		//
		// first check the cache
		//
		var thiz = this;
		var marker = this.nodes2markers[forWhom];
		if (marker) {
			if (showNow) {
				fHtml(function(html) {
								thiz.openHtml(marker,html);
							});
			}
			return;
		}
		var lon = point.getLon();
		var lat = point.getLat();
		var point = new GPoint(lon,lat);
		//var point = new GLatLng(lat,lon);
		marker = new GMarker(point);
		this.nodes2markers[forWhom] = marker;
		var m = this.map;
		m.addOverlay(marker);

		var f = function(_overlay,point) {
			fHtml(function(html) {
							thiz.openHtml(marker,html);
							m.centerAtLatLng(point);
						});
		};
		GEvent.addListener(marker, "click", f);
		if (showNow) f(0,0);		
	},

	openHtml: function(marker,html) {
		if (typeof html == 'string') {
			var newHTML = this._htmlStart() + html + this._htmlEnd();
			marker.openInfoWindowHtml(newHTML);
		} else {
			var newHTML = this._htmlStartDOM();
			newHTML.appendChild(html);
			marker.openInfoWindow(newHTML);
		}
	},

	/**
	 * @interface
	 */
	zoomTo: function(level) {
		this.map.zoomTo(level);
	},

	_dummy: function() {}
};

Jeff.Point = Class.create();
Jeff.Point.prototype = {

	initialize: function(lon,lat) {
		this.lon = lon;
		this.lat = lat;
	},

	getLon: function() {return this.lon;},
	getLat: function() {return this.lat;},

	toString: function() {
		return "(" + this.getLon() + "," + this.getLat() + ")";
	}

};


