/**
 * HYSMaps, Javascript file
 * 
 * The Have Your Say UGC Map system is a framework for
 * visualising geographically specific user-generated content 
 *
 * @author Rob Stanford <rob.stanford@airlock.com>
 * @version 2.1
 * @copyright Copyright (c) 2008 Airlock Limited <http://www.airlock.com>
 */

/**
 * Main namespace and constants
 */
var HYSMaps = {
	
	type: {
		road:		1,
		aerial:		2,
		hybrid:		3,
		terrain:	4
	},
	zoom: {
		minimum:	1,
		maximum:	12
	},
	clustering: {
		grid:		50,
		threshold:	5
	},
	defaults: {
		latitude:	51.5001,
		longitude: -0.1262,
		zoom:		8
	},
	modes: {
		input:		0,
		output:		1
	},
	filtering: {
		cutoff:		250,
		maximum:	500
	},
	
	mode:			0,
	
	assets:			'/nol/shared/bsp/hi/have_your_say/maps/airlock/2_2/ui/'
};


/**
 * Handler function to setup dom and control input
 */
HYSMaps.MapHandler = function (element) {

	this.dom = {
		
		base: element,
		wrapper: document.createElement('div'),
		map: document.createElement('div')
	};

	this.dom.map.id = 'map-canvas';
	this.dom.map.style.width = '100%';
	this.dom.map.style.height = '100%';
	this.dom.map.style.position = 'relative';
	
	this.dom.wrapper.className = 'map-container';
	
	this.dom.wrapper.appendChild(this.dom.map);
	this.dom.base.appendChild(this.dom.wrapper);
	
	// add unload handler to clean up objects
	window.onunload = this.unload.bind(this, window.onunload);
};

/**
 * Instantiates the input map for locating a user
 */
HYSMaps.MapHandler.prototype.input = function (coords, location, clear, icon) {
	
	this.map = new HYSMaps.InputMap(new HYSMaps.MapFactory(this.dom.map, HYSMaps.modes.input), coords, location, clear, icon);
	this.map.initialise();
	return this.map;
};

/**
 * Instantiates the output map for displaying generated content
 */
HYSMaps.MapHandler.prototype.output = function (input) {
	
	this.map = new HYSMaps.OutputMap(new HYSMaps.MapFactory(this.dom.map, HYSMaps.modes.output), input, this.dom.base);
	this.map.initialise();
	return this.map;
};

HYSMaps.MapHandler.prototype.unload = function (chain) {
	
	if (this.map) this.map.unload();
	if (chain) chain(); // call any existing unload handlers
};


/**
 * Map Factory class to handle selection of the
 * relevent map abstraction
 */
HYSMaps.MapFactory = function (element, mode) {
	this.dom = element;
	this.dom.className += ' initialised';
	this.mode = mode;
};

HYSMaps.MapFactory.prototype.createMap = function (provider, type, plotterType) {
	
	/*var plotter = {} ;
	if (plotterType && plotterType.toLowerCase() == 'clustered'){
		plotter = new HYSMaps.ClusterPlotter();
	} else if (plotterType && plotterType.toLowerCase() == 'input'){
		plotter = new HYSMaps.InputPlotter();
	} else {
		plotter = new HYSMaps.MarkerPlotter();
	}*/
	
	var plotter = (plotterType && plotterType.toLowerCase() == 'clustered') ? new HYSMaps.ClusterPlotter() : (plotterType && plotterType.toLowerCase() == 'input') ? new HYSMaps.InputPlotter() : new HYSMaps.MarkerPlotter() ;
	
	
	switch (provider.toLowerCase()) {
		
		case 'google':
			var map = new HYSMaps.GoogleMap(plotter);
			break;
			
		case 'microsoft':
			var map = new HYSMaps.MicrosoftMap(plotter);
			break;
	}
	
	HYSMaps.mode = this.mode;
	
	return map.initialise(this.dom, type);
};


(function () {
	
// bind event handlers with object context
Function.prototype.bind = function (object) {
	
	var method = this;
	var oldArguments = toArray(arguments).slice(1);
	return function (argument) {
		if (argument == Function.prototype.unbind) {
			method = null;
			oldArguments = null;
		} else if (method) {
			var newArguments = toArray(arguments);
			return method.apply(object, oldArguments.concat(newArguments));
		}
	};
};

Function.prototype.unbind = new Object;

// add inheritance
Function.prototype.inherits = function (superclass) { 
	
	var x = function () {}; 
	x.prototype = superclass.prototype; 
	this.prototype = new x(); 
};

function toArray(pseudoArray) {
	
	var result = [];
	for (var i = 0; i < pseudoArray.length; i++) {
		result.push(pseudoArray[i]);
	}
	return result;
};

})();


HYSMaps.isEmpty = function (object) {
	
	for (var i in object) return false;
	return true;
};


HYSMaps.InputParser = function () {};

HYSMaps.InputParser.prototype.parse = function (url, map) {
	
	// do ajax request to post back address
	this.ajax = new XMLHttpRequest();
	this.ajax.open('GET', url + '?' + Math.ceil(1000000 * Math.random()), true);
	this.ajax.onreadystatechange = this.onLoad.bind(this, map);
	this.ajax.send(null);
};

HYSMaps.InputParser.prototype.unescapeHTMLDecode=function(str) 
{
     var div=document.createElement('div');
	div.innerHTML=str;
	//console.log(div.textContent);
	return div.textContent || div.innerText;
};

HYSMaps.InputParser.prototype.onLoad = function (map) {
	
	if (this.ajax.readyState == 4) {

		var data = eval(this.ajax.responseText);
		var result = {
			map: data.map,
			series: {}
		};
		
		if (data.series) {
			
			for (var i in data.series) {
				
				if (data.series[i].typed) {
					var series = new HYSMaps.TypedSeries();
				} else {
					var series = new HYSMaps.Series();
				}
				
				for (var j = 0; j < data.series[i].points.length; ++j) { // loop through points
					
					var p = data.series[i].points[j]; // get point
					if (!p) continue;
					
					// get coordinates
					var split = p.coords.split(',');
					var x = parseFloat(split[0]);
					var y = parseFloat(split[1]);
	
					switch (i) {
						
						case 'comments':
							var point = new HYSMaps.CommentPoint();
							
							p.content = this.unescapeHTMLDecode(p.content); 
							if (!point.initialise(p.date, p.name, p.content, new HYSMaps.GeoCoords(y, x), p.type, p.link, p.alert)) {
								continue;
							}
							break;
						case 'audio':
							var point = new HYSMaps.AudioPoint();
							if (!point.initialise(p.title, p.content, new HYSMaps.GeoCoords(y, x), p.audio)) {
								continue;
							}
							break;
						case 'reports':
							var point = new HYSMaps.ReportPoint();
							if (!point.initialise(p.title, p.content, new HYSMaps.GeoCoords(y, x), p.image, p.link)) {
								continue;
							}
							break;
						case 'video':
							var point = new HYSMaps.VideoPoint();
							if (!point.initialise(p.title, p.content, new HYSMaps.GeoCoords(y, x), p.playlist, p.image)) {
								continue;
							}
							break;
					}
					
					if (!data.series[i].typed) p.type = null;
					series.addPoint(point, p.type);
				}
				
				if (series.initialise(data.series[i].name, data.series[i].icon, data.series[i].grouped)) {
					result.series[i] = series;
				}
			}
		}
		
		map.onData(result);
	}
};


// create AJAX wrapper for IE
if (typeof XMLHttpRequest == 'undefined') {
	
	XMLHttpRequest = function () {
		
		return new ActiveXObject(
			//IE 5 uses a different XMLHTTP object from IE 6
			navigator.userAgent.indexOf('MSIE 5') >= 0 ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP'
		);
	};
}