// Google Maps plugin by Avi Alkalay
// License LGPL
// http://avi.alkalay.net/2006/11/google-maps-plugin-for-wordpress.html




/* Would like to extend Element with Element.prototype but its not supported on IE6.
   So I have to define next 2 methods in an ungly, non-OO way. */

function firstChildElement(elem) {
	var walker=elem.firstChild;
//	var i;

	while (walker && (walker.nodeType != 1)) walker=walker.nextSibling;

//	alert(i + " child itarations: " + walker.nodeName);

	return walker;
}



function nextSiblingElement(elem) {
	var walker=elem.nextSibling;

	while (walker && (walker.nodeType != 1)) walker=walker.nextSibling;

	// alert(i + " sibling itarations: " + walker.nodeName);

	return walker;
}






function MapData(elem, commandsAttributeName, defaultW, defaultH) {
	// DOM related stuff
	this.elem=elem;
	this.inheritedStyle=null;
	this.className=null;
	this.inheritedID=null;
	this.defaultW=defaultW;
	this.defaultH=defaultH;

	this.commandsAttributeName=commandsAttributeName;

	// Map related stuff
	this.geoCoord=null;
	this.zoom=null;
	this.overviewMapControl=true;
	this.type=G_NORMAL_MAP;
	this.controls=true;
	this.showMarkers=true;

	this.detaultGeoCoord=new GLatLng(-15.779699,-47.910004);

	// The markers including baloon text, position, etc
	this.markers=[];
}



MapData.prototype.createGoogleMap = function() {
	var realMap;
	var mapNode;

	mapNode = document.createElement("div");

	if (this.className) mapNode.className = "map " + this.className;
	else mapNode.className = "map";

	if (this.inheritedStyle) mapNode.style.cssText = this.inheritedStyle;

	mapNode.style.display = "block";

	this.elem.parentNode.replaceChild(mapNode, this.elem);


	if (mapNode.style.width == 0) {
		if (this.defaultW.toString().indexOf("%")!=-1)
			mapNode.style.width = this.defaultW;
		else mapNode.style.width = this.defaultW + "px";
	}

	if (mapNode.style.height == 0) {
		if (this.defaultH.toString().indexOf("%")!=-1)
			mapNode.style.height = this.defaultH;
		else mapNode.style.height = this.defaultH + "px";
	}

	if (this.inheritedID) mapNode.id = this.inheritedID;
	else mapNode.id = "googlemap-" + Math.ceil(10000*Math.random());

	realMap = new GMap2(mapNode);

	realMap.setCenter(this.geoCoord, parseInt(this.zoom));


	if (this.controls) {
		if (parseInt(mapNode.style.height)>=320)
			realMap.addControl(new GLargeMapControl());
		else realMap.addControl(new GSmallMapControl());

		realMap.addControl(new GMapTypeControl());
		realMap.addControl(new GScaleControl());

		if (this.overviewMapControl)
			realMap.addControl(new GOverviewMapControl());
	}

	realMap.setMapType(this.type);

	if (this.showMarkers) {
		var manager=new GMarkerManager(realMap);
	
		manager.addMarkers(this.markers,1);
		manager.refresh();
	}
}



MapData.prototype.parseGoogleMapsURL = function(gmapsurl) {
	if (gmapsurl.indexOf("http://maps.google.")==-1) return 0;

	var i;
	var params = gmapsurl.split("?");
	params = params[1].split("&");

	for (i=0; i<=params.length-1; i++) {
		var param = params[i].split("=");
		switch (param[0]) {
			case "sll":
			case "ll": {
				var _geocoord = param[1].split(",");
				if (_geocoord[0]!=null || _geocoord[1]!=null) {
					this.geoCoord=new GLatLng(_geocoord[0],_geocoord[1]);
				}
				//alert("found long lat:"+ll[0]+"/"+ll[1]);
			}
			break;
			case "z": {
				this.zoom = param[1];
			}
			break;
			case "om": {
				this.overviewMapControl = (param[1]==0 ? false : true);
			}
			break;
			case "t": {
				switch (param[1]) {
					case 'k': this.type=G_SATELLITE_MAP;
					break;
					case 'h': this.type=G_HYBRID_MAP;
				}
			}
			break;
		}
	}
	return 1;
}



MapData.prototype.parseCommands = function(commands) {
	if (commands == undefined) return 0;

	if (commands.indexOf("googlemap") == -1) return 0;

//	alert("This is a googlemap");

	var params=commands.split(";");
	var i;

	for (i=0; i<params.length; i++) {
//		alert("Parsing \"" + params[i] + "\"");
		if (params[i].indexOf("nomarker")!=-1) {
			this.showMarkers=false;
		} else if (params[i].indexOf("w:")!=-1) {
			var val = params[i].split(':');
			this.defaultW=val[1];
		} else if (params[i].indexOf("h:")!=-1) {
			var val = params[i].split(':');
			this.defaultH=val[1];
		} else if (params[i].indexOf("nocontrol")!=-1) {
			this.controls=false;
		}
	}
	return 1;
}


MapData.prototype.addMarker = function(point,markerHTML) {
	var marker = new GMarker(point);

	if (markerHTML) GEvent.addListener(marker, "click", function() {
			var opts = { maxWidth : 450 };
			marker.openInfoWindowHtml("<div class=\"balloon\" style=\"width:auto;height:auto\">"+markerHTML+"</div>", opts);
		});

	this.markers.push(marker);
}



MapData.prototype.parseAnchorTag = function(commandsAttributeName) {
	if (!this.parseCommands(this.elem.getAttribute(commandsAttributeName))) return 0;

	if (!this.parseGoogleMapsURL(this.elem.href)) return 0;
	if (this.geoCoord == null) this.geoCoord=this.defaultGeoCoord;

	if (this.elem.style.cssText) this.inheritedStyle=this.elem.style.cssText;
	if (this.elem.className) this.className=this.elem.className;
	if (this.elem.id) this.inheritedID=this.elem.id;

	this.addMarker(this.geoCoord, this.elem.innerHTML);

	return 1;
}





MapData.prototype.parseDefinitionBlock = function(commandsAttributeName) {
	if (!this.parseCommands(this.elem.getAttribute("title"))) return 0;

	var walker;

	if (this.elem.style.cssText) this.inheritedStyle=this.elem.style.cssText;
	if (this.elem.className) this.className=this.elem.className;
	if (this.elem.id) this.inheritedID=this.elem.id;

	this.elem.title=null; // Get rid of "googlemap" and friends commands

//	alert("Found a map with id=" + this.inheritedID);


	walker=firstChildElement(this.elem);  // Points to first <dt>

	// Proccess each <dt> and <dd> pair
	while (walker && walker.nodeName.toLowerCase() == "dt") {
		// Get an <a> with the marker's position
		var elem=firstChildElement(walker);

		if (!elem) {
			// Empty <dt></dt>
			// Iterate until next <dt>
			do walker=nextSiblingElement(walker);
			while (walker && walker.nodeName.toLowerCase() != "dt");

			// Restart loop
			continue;
		}

//		alert("Parsing element " + elem.nodeName);

		if (elem.nodeName.toLowerCase() == "a") {
			if (this.geoCoord==null) {
				// We still don't have a center point, so the first <a> is the center of map
				this.parseGoogleMapsURL(elem.href); // && alert("Found a center point");

				do walker=nextSiblingElement(walker); // move to next <dt>
				while (walker && walker.nodeName.toLowerCase() != "dt");

				continue;
			} else {
				// We already have a center point, so this is a plain marker
				var tempMapData=new MapData();

				if (!tempMapData.parseGoogleMapsURL(elem.href)) {
					do walker=nextSiblingElement(walker); // move to next <dt>
					while (walker && walker.nodeName.toLowerCase() != "dt");

					continue;
				}

				// We already have the marker position, now get the HTML for the balloon

				// Make walker point to <dd>
				do walker=nextSiblingElement(walker);
				while (walker && (walker.nodeName.toLowerCase() != "dd" && walker.nodeName.toLowerCase() != "dt"));

				if (walker && walker.nodeName.toLowerCase() == "dd") {
					this.addMarker(tempMapData.geoCoord,walker.innerHTML);
//					alert("Found a marker point. Balloon is: " + walker.innerHTML);
				} else this.addMarker(tempMapData.geoCoord); // Marker with no balloon
			}
		}

//		alert("Looking for next <dt>. Walker=" + walker.nodeName.toLowerCase());

		// Parsed a center <dt> ar a <dt>+<dd> pair. Seek next <dt>.
		while (walker && walker.nodeName.toLowerCase() != "dt")
			walker=nextSiblingElement(walker); // move to next <dt>
	}

	if (this.geoCoord==null) return 0;
	else return 1;
}




MapData.prototype.parseListBlock = function(commandsAttributeName) {
	if (!this.parseCommands(this.elem.getAttribute("title"))) return 0;

	var walker;

	if (this.elem.style.cssText) this.inheritedStyle=this.elem.style.cssText;
	if (this.elem.className) this.className=this.elem.className;
	if (this.elem.id) this.inheritedID=this.elem.id;

	this.elem.title=null; // Get rid of "googlemap" and friends commands

//	alert("Found a map with id=" + this.inheritedID);

	walker=firstChildElement(this.elem);  // Points to first <li>
	do { // Proccess each <li>
		var elem=firstChildElement(walker); // Get an <a> with the marker's position

		if (!elem) continue; // Empty <li></li>

//		alert("Parsing element " + elem.nodeName);

		if (elem.nodeName.toLowerCase() == "a" && elem.getAttribute(commandsAttributeName).indexOf("center")!=-1) {
			// We got the center point.
			if (!this.parseGoogleMapsURL(elem.href)) continue;

//			alert("Found a center point");

			// Nothing else to do with this <li>. Jump to next <li>.
			continue;
		}

		var tempMapData=null;

		if (elem.nodeName.toLowerCase() == "a" && elem.getAttribute(commandsAttributeName).indexOf("marker")!=-1) {
			tempMapData=new MapData();
			if (!tempMapData.parseGoogleMapsURL(elem.href)) continue;
		}
		
		do
			// Jump all kind of junk until we get a <p title="balloon"> node
			elem=nextSiblingElement(elem);
		while (elem && !(elem.nodeName.toLowerCase() == "p" && elem.getAttribute("title").indexOf("balloon")!=-1))

		if (elem) {
			this.addMarker(tempMapData.geoCoord,elem.innerHTML);
//			alert("Got a balloon: " + elem.innerHTML);
		}

	} while (walker=nextSiblingElement(walker));
	
	return 1;
}






MapData.prototype.parseNode = function () {
	switch (this.elem.nodeName.toLowerCase()) {
		case "dl":
			if (!this.parseDefinitionBlock(this.commandsAttributeName))
				return 0;
		break;
		case "ul":
			if (!this.parseListBlock(this.commandsAttributeName))
				return 0;
		break;
		case "a":
			if (!this.parseAnchorTag(this.commandsAttributeName))
				return 0;
	}
	return 1;
}





MapPlugin.prototype.consumeMapContainers = function() {
	var mapContainers=["dl","ul","a"];

	var attributeForCommands="title";
	var i1;
	var i2;


//	alert("Default sizes: " + this.defaultW + ", " + this.defaultH);
//	alert("User rel: " + this.userRelAttribute);

	if (this.useRelAttribute)
		attributeForCommands="rel";

	for (i1=0; i1<mapContainers.length; i1++) {
		var elems=document.getElementsByTagName(mapContainers[i1]);

		for (i2=0; i2<elems.length; i2++) {
			var map = new MapData(elems[i2],attributeForCommands,this.defaultW,this.defaultH);

			if (! map.parseNode()) continue;

//			alert("Going to create a map with ID=" + map.inheritedID);
			map.createGoogleMap();
		}
	}
}





function MapPlugin(_defaultWidth, _defaultHeight, _useRelAttribute) {
	this.defaultW = _defaultWidth;
	this.defaultH = _defaultHeight;
	this.userRelAttribute = _useRelAttribute;

	this.consumeMapContainers();
}




function MapPluginInit(_defaultWidth, _defaultHeight, _useRelAttribute) {
	if (! GBrowserIsCompatible()) return;

	var oldOnLoad = window.onload;
	var oldOnUnload = window.onunload;

	var instantiate = function() {
		new MapPlugin(_defaultWidth, _defaultHeight, _useRelAttribute);
	}

	if (typeof window.onload != 'function')
		window.onload = instantiate;
	else window.onload = function() {
		oldOnLoad();
		instantiate();
	}
/*
	if (typeof window.onunload != 'function')
			window.onunload = GUnload();
	else window.onunload = function() {
		oldOnUnload();
		GUnload()
	}
*/
}



