/*

Geo Mashup - Adds a Google Maps mashup of geocoded blog posts.

Copyright (c) 2005-2007 Dylan Kuhn



This program is free software; you can redistribute it

and/or modify it under the terms of the GNU General Public

License as published by the Free Software Foundation;

either version 2 of the License, or (at your option) any

later version.



This program is distributed in the hope that it will be

useful, but WITHOUT ANY WARRANTY; without even the implied

warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR

PURPOSE. See the GNU General Public License for more

details.

*/



var GeoMashup = {

	posts : [],

	locations : [],

	loading : false,

	firstLoad : true,



	registerMap : function(container, opts) {

		if (document.all&&window.attachEvent) { // IE-Win

			window.attachEvent("onload", function () { GeoMashup.createMap(container, opts); });

		  window.attachEvent("onunload", GUnload);

		} else if (window.addEventListener) { // Others

			window.addEventListener("load", function () { GeoMashup.createMap(container, opts); }, false);

			window.addEventListener("unload", GUnload, false);

		}

	},



	log : function(message,color) {

		if (this.opts.showLog) {

			GLog.write(message,color);

		}

	},



	getCookie : function(NameOfCookie) { 

		if (document.cookie.length > 0) { 

			var begin = document.cookie.indexOf(NameOfCookie+"=");

			if (begin != -1) { 

				begin += NameOfCookie.length+1;

				var end = document.cookie.indexOf(";", begin);

				if (end == -1) end = document.cookie.length;

				return unescape(document.cookie.substring(begin, end)); 

			}

		}

		return null;

	},



	setCookie : function(NameOfCookie, value) { 

		document.cookie = NameOfCookie + "=" + escape(value); 

	},



	delCookie : function(NameOfCookie) { 

		if (this.getCookie(NameOfCookie)) {

			document.cookie = NameOfCookie + "=" +

				"; expires=Thu, 01-Jan-70 00:00:01 GMT";

		}

	},



	getTagContent : function (parent, tag, default_value) {

		if (!default_value) {

			default_value = '';

		}

		var children = parent.getElementsByTagName(tag);

		if (children.length > 0 && children[0].firstChild) {

			return children[0].firstChild.nodeValue;

		} else {

			return default_value;

		}

	},



	renderRss : function (rss_doc) {

		var items = rss_doc.getElementsByTagName('item');

		if (items.length == 0) return false;

		this.log('Render ' + items.length + ' items from RSS');

		var html = ['<div class="locationinfo">'];

			

		for (var i=0; i<items.length; i++) {

			var link = this.getTagContent(items[i],'link');

			var url = link;

			var onclick = 'GeoMashup.setBackCookies()';

			if (this.opts.showPostHere) {

				onclick = 'GeoMashup.showPost(\''+url+'\')';

				url = '#geoPost';

			}

			var title = this.getTagContent(items[i],'title','-');

			var pubDate = this.getTagContent(items[i],'pubDate','-').substr(0,16);

			var tags = [];

			var categories = items[i].getElementsByTagName('category');

			for (var j=0; j<categories.length; j++) {

				tags.push(categories[j].firstChild.nodeValue);

			}

			html = html.concat(['<h2><a href="', url, '" onclick="', onclick, '">',

				title,'<\/a><\/h2><p class="meta"><span class="blogdate"><strong>Post Date: <\/strong>',pubDate,'<\/span><br \/>','<strong>Categories: <\/strong>', tags.join(' | '),

				'<\/p>']);

			if (items.length == 1) {

				var desc = this.getTagContent(items[i],'description').replace('[...]','');

				html = html.concat(['<p class="storycontent">',desc,

					'<a href="',url,'" onclick="',onclick,'"> [...Read More]<\/a><\/p>']);

				if (this.opts.showPostHere) { this.showPost(link); }

			}

		} 

		html.push('<\/div>');

		return html.join('');

	},



	showPost : function (url) {

		this.log('Show post: ' + url);

		if (this.showing_url == url) {

			return false;

		}

		var geoPost = document.getElementById('geoPost');

		if (!geoPost) {

			this.opts.showPostHere = false;

			return false;

		}

		this.showing_url = url;

		var request = new GXmlHttp.create();

		geoPost.innerHTML = '';

		request.open('GET',url,true);

		request.onreadystatechange = function() {

			if (request.readyState == 4) {

				if (request.status == 200) {

					var node = document.createElement('div');

					node.innerHTML = request.responseText;

					var divs = node.getElementsByTagName('div');

					for (var i=0; i<divs.length; i++) {

						if (divs[i].className=='post') { 

							geoPost.appendChild(divs[i]);

							break;

						}

					}

				} else {

					geoPost.innerHTML = 'Request for '+url+' failed: '+request.status;

				}

			}

		}

		request.send(null);

	},



	createMarker : function(point,title) {

		this.log('Create a marker at ' + point);

		var marker_opts = {title:title};

		if (this.marker_icon) {

			marker_opts.icon = this.marker_icon;

		}

		var marker = new GMarker(point,marker_opts);



		// Show this markers index in the info window when it is clicked

		GEvent.addListener(marker, "click", function() {

			// The loading window is late to show up - may replace it 

			// with a message div 

			marker.openInfoWindowHtml('Loading...');

			GeoMashup.loading = true;

		});



		GEvent.addListener(marker, "infowindowopen", function() {

			if (GeoMashup.loading) {

				var request = new GXmlHttp.create();

				GeoMashup.log('Load all posts at ' + point);

				for(var i=0; i<GeoMashup.locations[point].posts.length; i++) {

					var post_id = GeoMashup.locations[point].posts[i];

					if (!GeoMashup.locations[point].loaded[post_id]) {

						GeoMashup.log('The XML for post ' + post_id + ' has not been loaded, request it');

						var url = GeoMashup.opts.linkDir + '/geo-query.php?post_id=' + post_id;

						// Use a synchronous request to simplify multiple posts at a location

						request.open('GET', url, false);

						try {

							request.send(null);

							if (!GeoMashup.locations[point].xmlDoc) {

								GeoMashup.log('This is the only post here, use the XML as it is');

								GeoMashup.locations[point].xmlDoc = request.responseXML;

							} else {

								GeoMashup.log('There are multiple posts here, append this one to the others');

								var newItem = request.responseXML.getElementsByTagName('item')[0];

								var channel = GeoMashup.locations[point].xmlDoc.getElementsByTagName('channel')[0];

								channel.appendChild(newItem);

							} 

							GeoMashup.locations[point].loaded[post_id] = true;

						} catch (e) {

							alert('Request for ' + url + ' failed: ' + e);

						}

					} // end if not loaded

				} // end location posts loop

				GeoMashup.loading = false;

				var html = GeoMashup.renderRss(GeoMashup.locations[point].xmlDoc);

				marker.openInfoWindowHtml(html);

			} 

		}); // end marker infowindowopen



		GEvent.addListener(marker, 'infowindowclose', function() {

			GeoMashup.log('Closed the infowindow');

			var geoPost = document.getElementById('geoPost');

			if (geoPost && geoPost.firstChild) {

				geoPost.removeChild(geoPost.firstChild);

				GeoMashup.showing_url = '';

			}

		});



		return marker;

	},



	checkDependencies : function () {

		this.log('Check browser compatibility');

		if (typeof(GMap) == "undefined" || !GBrowserIsCompatible()) {

			this.container.innerHTML = '<p class="errormessage">' +

				'Sorry, the Google Maps script failed to load. Have you entered your ' +

				'<a href="http://maps.google.com/apis/maps/signup.html">API key<\/a> ' +

				'in the <a href="' + this.opts.linkDir + 

				'../../../wp-admin/options-general.php?page=geo-mashup/geo-mashup.php">' +

				'Geo Mashup Options<\/a>?';

			throw "The Google Maps javascript didn't load.";

		}

	},



	clickCenterMarker : function() {

		this.log('If there is a marker at the center, click it');

		var center = this.map.getCenter();

		if (this.locations[center]) {

			GEvent.trigger(this.locations[center].marker,"click");

		}

	},



	createMap : function(container, opts) {

		this.container = container;

		this.opts = opts;

		this.showing_url = '';

		this.checkDependencies();

		this.map = new GMap2(this.container);

		GEvent.addListener(this.map, "moveend", function() {

			GeoMashup.log('Moved the map, query for new visible locations');

			var request = GXmlHttp.create();

			var bounds = GeoMashup.map.getBounds();

			var url = GeoMashup.opts.linkDir + '/geo-query.php?minlat=' +

				bounds.getSouthWest().lat() + '&minlon=' + bounds.getSouthWest().lng() + '&maxlat=' +

				bounds.getNorthEast().lat() + '&maxlon=' + bounds.getNorthEast().lng();

			if (GeoMashup.opts.cat) {

				url += '&cat=' + GeoMashup.opts.cat;

			}

			request.open("GET", url, true);

			request.onreadystatechange = function() {

				GeoMashup.log('Request state ' + request.readyState);

				if (request.readyState == 4 && request.status == 200) {

					var response_data = eval(request.responseText);

					for (var i = 0; i < response_data.length; i++) {

						// Make a marker for each new post location

						var post_id = response_data[i].post_id;

						if (!GeoMashup.posts[post_id]) {

							// This post has not yet been loaded

							var point = new GLatLng(

								response_data[i].lat,

								response_data[i].lng);

							if (!GeoMashup.locations[point]) {

								// There are no other posts yet at this point, create a marker

								GeoMashup.locations[point] = new Object();

								GeoMashup.locations[point].posts = new Array();

								GeoMashup.locations[point].posts.push(post_id);

								GeoMashup.locations[point].loaded = new Array();

								GeoMashup.posts[post_id] = true;

								var marker = GeoMashup.createMarker(point,response_data[i].title);

								GeoMashup.locations[point].marker = marker;

								GeoMashup.map.addOverlay(marker);

							} else {

								// There is already a marker at this point, add the new post to it

								GeoMashup.locations[point].posts.push(post_id);

								GeoMashup.posts[post_id] = true;

							}

						}

					} // end for each marker

					if (GeoMashup.firstLoad) {

						GeoMashup.firstLoad = false;

						if (GeoMashup.opts.autoOpenInfoWindow) {

							GeoMashup.clickCenterMarker();

						}

					}

				} // end readystate == 4

			} // end onreadystatechange function

			request.send(null);

		});



		if (opts.loadLat && opts.loadLon) {

			this.log('Center at' + opts.LoadLat + ',' + opts.LoadLon);

			this.loadLat = opts.loadLat;

			this.loadLon = opts.loadLon;

		} else {

			this.log('Look for load settings in cookies');

			this.loadLat = this.getCookie("loadLat");

			this.loadLon = this.getCookie("loadLon");

		}

		if (opts.loadZoom)

		{

			this.log('Zoom option ' + opts.loadZoom);

			this.loadZoom = opts.loadZoom;

		} else {

			var cookieZoom = parseInt(this.getCookie("loadZoom"));

			if (cookieZoom) {

				this.log('Zoom level ' + cookieZoom + ' from cookie');

				this.loadZoom = cookieZoom;

			} else if (typeof(opts.defaultZoom) != 'undefined') {

				this.log('Zoom level ' + opts.defaultZoom + ' from default');

				this.loadZoom = opts.defaultZoom;

			} else {

				this.log('Zoom level 5, last resort');

				this.loadZoom = 5;

			}

		}

		// Use default map type if appropriate

		if (!this.loadType) {

			var cookieTypeNum = parseInt(this.getCookie("loadType"));

			if (cookieTypeNum) {

				this.log('Load type ' + cookieTypeNum + ' from cookie');

				this.loadType = this.map.getMapTypes()[cookieTypeNum];

			} else if (opts.defaultMapType) {

				this.log('Load type ' + opts.defaultMapType + ' from default');

				this.loadType = opts.defaultMapType;

			} else {

				this.log('Load normal type, last resort');

				this.loadType = G_NORMAL_MAP;

			}

		} 



		if (this.loadLat && this.loadLon && typeof(this.loadZoom) != 'undefined') {

			this.log('Center map based on load settings');

			this.map.setCenter(new GLatLng(this.loadLat, this.loadLon), this.loadZoom, this.loadType);

		} else {

			this.log('Query the most recent geo-tagged post and center there');

			var request = GXmlHttp.create();

			var url = this.opts.linkDir + '/geo-query.php';

			if (opts.cat) {

				url += '?cat='+opts.cat;

			}

			request.open("GET", url, false);

			request.send(null);

			var posts = eval(request.responseText);

			if (posts.length>0) {

				var point = new GLatLng(posts[0].lat,posts[0].lng);

				this.log('Most recent post at ' + point);

				this.map.setCenter(point,this.loadZoom,this.loadType);

			} else {

				this.log('No posts available - center at 0,0');

				this.map.setCenter(new GLatLng(0,0),this.loadZoom,this.loadType);

			}

		}



		this.log('Add controls');

		if (opts.mapControl == 'GSmallZoomControl') {

			this.map.addControl(new GSmallZoomControl());

		} else if (opts.mapControl == 'GSmallMapControl') {

			this.map.addControl(new GSmallMapControl());

		} else if (opts.mapControl == 'GLargeMapControl') {

			this.map.addControl(new GLargeMapControl());

		}

		

		if (opts.addMapTypeControl) {

			this.map.addControl(new GMapTypeControl());

		}



		if (opts.addOverviewControl) {

			this.map.addControl(new GOverviewMapControl());

			var ov = document.getElementById('geoMashup_overview');

			if (ov) {

				ov.style.position = 'absolute';

				this.container.appendChild(ov);

			}

		}



		if (this.addCategoryControl) {

			this.map.addControl(new GeoMashupCategoryControl());

		}



		if (this.customizeMap) {

			this.log('The customizeMap user function exists, call it');

			this.customizeMap();

		}



	},

		

	setBackCookies : function() {

		this.log('Set cookies to remember map position');

		var center = this.map.getCenter();

		var mapTypeNum = 0;

		for(var ix=0; ix<this.map.getMapTypes().length; ix++){

			if(this.map.getMapTypes()[ix]==this.map.getCurrentMapType())

				mapTypeNum=ix;

		}

		this.setCookie("loadType",mapTypeNum);

		this.setCookie("loadLat",center.lat());

		this.setCookie("loadLon",center.lng());

		this.setCookie("loadZoom",this.map.getZoom());

		return true;

	}

};



