
var MapTypes = { Road:1, Satellite:2, Hybrid:3 };

var MapUnits = { Miles:1, Kilometers:2 };

var MapPoint = Class.extend({
	latitude: null,
	longitude: null,
	init: function(latitude, longitude) {
		this.latitude = parseFloat(latitude);
		this.longitude = parseFloat(longitude);
	}
});

var MapPixel = Class.extend({
	x: null,
	y: null,
	init: function(x, y) {
		this.x = x;
		this.y = y;
	}
});

var MapMarkerIcon = Class.extend({
	image: null,
	size: new MapPixel(0, 0),
	offset: new MapPixel(0, 0),
	text: null,
	textOffset: new MapPixel(0,0),
	textSize: null,
	textColor: null,
	init: function(image, size) {
		this.image = image;		
		this.size = size;
	}
});

var _MapMarkerNextID = 1; 
var MapMarker = Class.extend({
	id: null,
	point: null,
	content: null,
	visible: true,
	events: null,
	icon: null,
	clickable: true,
	draggable: false,
	tooltip: null,
	init: function(point, content) {
		this.id = _MapMarkerNextID++;
		this.point = point || new MapPoint(0,0);
		this.content = content;
		this.events = new Array();
	},
	bind: function(ev, fn) {
		if (ev && fn) {
			this.events.push([ev,fn]);
		}
	},
	unbind: function(ev, fn) {
		if (ev && fn) {
			for (var i = this.events.length - 1; i >= 0; i--) {
				if (this.events[i][0] == ev && this.events[i][1] == fn) {
					this.events.splice(i, 1);
				}
			}
		}
	},
	unbindAll: function() {
		this.events = new Array();
	}
});

var MapDirectionsStep = Class.extend({
	instruction: null,
	distance: null,
	time: null,
	point: null,
	init: function(instruction, distance, time, point) {
		this.instruction = instruction;
		this.distance = distance;
		this.time = time;
		this.point = point || new MapPoint(0,0);
	}
});

var MapDirections = Class.extend({
	ids: null,
	distance: null,
	time: null,
	steps: null,
	visible: null,
	callback: null,
	init: function(ids, distance, time, visible) {
		this.ids = ids;
		this.distance = distance;
		this.time = time;
		this.visible = (visible == false) ? false : true;
		this.steps = new Array();
	}
});

var IMap = Class.extend({
	id: null,
	container: null,
	isLoaded: false,
	init: function(id) {
		this.id = id;
		this.container = $("#" + id);
		this.unit = MapUnits.Miles;
		this.markers = new Array();
		this.events = new Array();
		this.directions = null;
	},
	load: function(params) {
		if (!this.defaultCursor) {
			this.defaultCursor = this.getCursor();
		}
		this.setParameters(params);
		this.isLoaded = true;
	},
	show: function() {
		this.container.show();
	},
	hide: function() {
		this.container.hide();
	},
	resize: function() {},
	getParameters: function() {
		var params = new Array();
		params["type"] = this.getMapType();
		params["unit"] = this.getMapUnit();
		params["overview"] = this.getOverviewVisible();
		params["cursor"] = this.getCursor();
		params["markers"] = this.markers;
		params["events"] = this.events;
		params["directions"] = this.directions;
		params["point"] = this.getPosition();
		params["zoom"] = this.getZoom();
		return params;
	},
	setParameters: function(params) {
		if (params) {
			this.setMapType(params["type"]);
			this.setMapUnit(params["unit"]);
			this.setOverviewVisible(params["overview"]);
			this.setCursor(params["cursor"]);
			
			this.unmarkAll();
			for (var i in params["markers"]) {
				this.mark(params["markers"][i]);
			}			

			this.unbindAll();
			for (var i in params["events"]) {
				this.bind(params["events"][i][0],params["events"][i][1]);
			}

			this.clearDirections();
			if (params["directions"]) {
				this.setDirections(params["directions"].ids, params["directions"].callback, params["directions"].visible);
			}			

			this.setPosition(params["point"],params["zoom"]);
		}
	},
	getPosition: function() {return new MapPoint();},
	setPosition: function(point, zoom) {},
	getLatitude: function() {
		return this.getPosition().latitude;
	},
	setLatitude: function(latitude) {
		this.setPosition(new MapPoint(latitude || 0, this.getPosition().longitude));
	},
	getLongitude: function() {
		return this.getPosition().longitude;
	},
	setLongitude: function(longitude) {
		this.setPosition(new MapPoint(this.getPosition().latitude, longitude || 0));
	},
	getZoom: function() {return null;},
	setZoom: function(zoom) {},
	getMapType: function() {return null;},
	setMapType: function(type) {},
	getMapUnit: function() {return this.unit;},
	setMapUnit: function(unit) {
		this.unit = unit;
	},
	getOverviewVisible: function() {return null;},
	setOverviewVisible: function(visible) {},
	getCursor: function() {return null},
	setCursor: function(cursor) {},
	framePoints: function(points) {},
	mark: function(marker) {
		if (marker) {
			this.markers.push(marker);
		}
	},
	unmark: function(id) {
		if (id) {
			for (var i in this.markers) {
				if (this.markers[i].id == id) {
					this.markers.splice(i, 1);
					break;
				}
			}
		}
	},
	unmarkAll: function() {
		this.markers = new Array();
		this.clearDirections();
	},
	moveMarker: function(id, point) {
		if (id && point) {
			var m = this.getMarker(id);
			if (m) {
				m.point = point;
			}
		}
	},
	updateMarkerContent: function(id, content) {
		if (id) {
			var m = this.getMarker(id);
			if (m) {
				m.content = content;
			}
		}
	},
	showMarkerContent: function(id, content) {},
	hideMarkerContent: function() {},
	frameMarkers: function(fm) {
		var points = new Array();
		for (var i in this.markers) {
			if (this.markers[i].visible && (!fm || $.inArray(this.markers[i].id, fm) >= 0)) {
				points.push(new MapPoint(this.markers[i].point.latitude, this.markers[i].point.longitude));
			}
		}
		this.framePoints(points);
	},
	setMarkerVisibility: function(id, visible) {
		if (id) {
			var m = this.getMarker(id);
			if (m) {
				m.visible = visible;
			}
		}
	},
	getMarker: function(id) {
		if (id) {
			for (var i in this.markers) {
				if (this.markers[i].id == id) {
					return this.markers[i];
					break;
				}
			}
		}
		return null;		
	},
	bind: function(ev, fn) {
		if (ev && fn) {
			this.events.push([ev,fn]);
		}
	},
	unbind: function(ev, fn) {
		if (ev && fn) {
			for (var i = this.events.length - 1; i >= 0; i--) {
				if (this.events[i][0] == ev && this.events[i][1] == fn) {
					this.events.splice(i, 1);
				}
			}
		}
	},
	unbindAll: function() {
		this.events = new Array();
	},
	getDirections: function() {
		return this.directions;
	},
	setDirections: function(ids, fn, visible) {},
	clearDirections: function() {
		this.directions = null;
	},
	resetDirections: function() {
		if (this.directions) {
			this.setDirections(this.directions.ids,this.directions.callback,this.directions.visible);
		}
	},
	frameDirections: function() {
		if (this.directions) {
			var points = new Array();
			if (this.directions.ids.length) {
				var m = this.getMarker(this.directions.ids[0]);
				if (m) {
					points.push(new MapPoint(m.point.latitude, m.point.longitude));				
				}
				m = this.getMarker(this.directions.ids[this.directions.ids.length - 1]);
				if (m) {
					points.push(new MapPoint(m.point.latitude, m.point.longitude));				
				} 
			}
			for (var i in this.directions.steps) {
				points.push(new MapPoint(this.directions.steps[i].point.latitude, this.directions.steps[i].point.longitude));
			}
			this.framePoints(points);			
		}
	},
	setDirectionsVisibility: function(visible) {
		if (this.directions) {
			this.directions.visible = visible;
		}
	}
});


var Mapper = IMap.extend({
	init: function(id, params) {
		this._super(id);
		this.container.addClass("mapper");
		this.maps = new Array();
		for (var key in params) {
			var mid = this.id + "_" + key;
			this.container.append($("<div/>").attr("id", mid).addClass("mapper-map").css("display","none"));
			this.maps[key] = new params[key](mid);
		}
	},
	load: function(map, params) {
		if (map) {
			params = $.extend(this.getParameters(),params);
			if (this.current) {
				this.current.hide();
			}
	
			this.current = this.maps[map];
			this.current.container.height(this.container.height());
			this.current.show();
			this.current.load(params);
			this.isLoaded = true;
		}
	},
	show: function() {
		if (this.current) {
			this.current.show();
		}
		this._super();
	},
	hide: function() {
		if (this.current) {
			this.current.hide();
		}
		this._super();
	},	
	resize: function() {
		if (this.current) {
			var pos = this.getPosition();
			this.current.container.height(this.container.height());
			this.current.resize();
			this.setPosition(pos);
		}
	},
	getParameters: function() { return this.current ? this.current.getParameters() : this._super(); },
	setParameters: function(params) {
		if (this.current) {
			this.current.setParameters(params);
		}
	},
	getPosition: function() {return this.current ? this.current.getPosition() : new MapPoint(0,0);},
	setPosition: function(point, zoom) {
		if (this.current) {
			this.current.setPosition(point, zoom);
		}
	},
	getZoom: function() { return this.current ? this.current.getZoom() : 2; },
	setZoom: function(zoom) {
		if (this.current) {
			this.current.setZoom(zoom);
		}
	},
	getMapType: function() { return this.current ? this.current.getMapType() : MapTypes.Road; },
	setMapType: function(type) {
		if (this.current) {
			this.current.setMapType(type);
		}
	},
	getMapUnit: function() { return this.current ? this.current.getMapUnit() : MapUnits.Miles; },
	setMapUnit: function(unit) {
		if (this.current) {
			this.current.setMapUnit(unit);
		}
	},
	getOverviewVisible: function() { return this.current ? this.current.getOverviewVisible() : true; },
	setOverviewVisible: function(visible) {
		if (this.current) {
			this.current.setOverviewVisible(visible);
		}
	},
	getCursor: function() { return this.current ? this.current.getCursor() : null; },
	setCursor: function(cursor) {
		if (this.current) {
			this.current.setCursor(cursor);
		}
	},
	framePoints: function(points) {
		if (this.current) {
			this.current.framePoints(points);
		}
	},
	mark: function(marker) {
		if (this.current) {
			this.current.mark(marker);
		}
	},
	unmark: function(id) {
		if (this.current) {
			this.current.unmark(id);
		}
	},
	unmarkAll: function() {
		if (this.current) {
			this.current.unmarkAll();
		}
	},
	moveMarker: function(id, point) {
		if (this.current) {
			this.current.moveMarker(id, point);
		}
	},
	frameMarkers: function(fm) {
		if (this.current) {
			this.current.frameMarkers(fm);
		}
	},
	updateMarkerContent: function(id, content) {
		if (this.current) {
			this.current.updateMarkerContent(id, content);
		}
	},
	showMarkerContent: function(id, content) {
		if (this.current) {
			this.current.showMarkerContent(id, content);
		}
	},
	hideMarkerContent: function() {
		if (this.current) {
			this.current.hideMarkerContent();
		}
	},
	setMarkerVisibility: function(id, visible) {
		if (this.current) {
			this.current.setMarkerVisibility(id, visible);
		}
	},
	getMarker: function(id) { return this.current ? this.current.getMarker(id) : null; },
	bind: function(ev, fn) {
		if(this.current) {
			this.current.bind(ev, fn);
		}
	},
	unbind: function(ev, fn) {
		if (this.current) {
			this.current.unbind(ev, fn);
		}
	},
	unbindAll: function() {
		if (this.current) {
			this.current.unbindAll();
		}
	},
	getDirections: function() { return this.current ? this.current.getDirections() : null; },
	setDirections: function(ids, fn, visible) {
		if(this.current) {
			this.current.setDirections(ids, fn, visible);
		}
	},
	clearDirections: function() {
		if (this.current) {
			this.current.clearDirections();
		}
	},
	resetDirections: function() {
		if (this.current) {
			this.current.resetDirections();
		}
	},
	frameDirections: function() {
		if (this.current) {
			this.current.frameDirections();
		}
	},
	setDirectionsVisibility: function(visible) {
		if (this.current) {
			this.current.setDirectionsVisibility(visible);
		}
	}
});

function GetDistance(point1, point2) {
	var lat1 = point1.latitude;
	var lon1 = point1.longitude;
	var lat2 = point2.latitude;
	var lon2 = point2.longitude;
	var earthRadius = 6372795; //appxoximate radius in meters
	var factor = Math.PI / 180;
	var dLat = (lat2-lat1)*factor;
	var dLon = (lon2-lon1)*factor;
	var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1*factor) * Math.cos(lat2*factor) * Math.sin(dLon/2) * Math.sin(dLon/2); 
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
	var d = earthRadius * c;
	return d;
}

// param distance in meters
function PrintDistance(distance, unit, full) {
	var name = full ? directionsMeters : directionsMetersAbbr;
	switch (unit) {
		case MapUnits.Miles:
			if (distance > 160.9344) {
				distance = (distance / 1609.344).toFixed(1);
				name = full ? directionsMiles : directionsMilesAbbr;
			} else {
				distance = (distance / 0.3048).toFixed(0);
				name = full ? directionsFeet : directionsFeetAbbr;
			}
			break;
		case MapUnits.Kilometers:
			if (distance > 100) {
				distance = (distance / 1000).toFixed(1);
				name = full ? directionsKilometers : directionsKilometers;
			} else {
				distance = distance.toFixed(0);
			}
			break;
	}
	return distance + " " + name;
}

// param time in seconds
function PrintTime(time) {
	if (time == null) {
		return "";
	} else if (isNaN(time)) {
		return (time + directionsHours);
	}
	
	var seconds = time % 60;
	var minutes = time - seconds;
	minutes = (minutes / 60) + (seconds > 0 ? 1 : 0);
	if (minutes >= 60) {
		var minLeft = minutes % 60;
		var hours = minutes - minLeft;
		hours = hours / 60;
                
                return (hours + (hours > 1 ? directionsHour : directionsHours) + (minLeft > 0 ? (", " + minLeft (minLeft > 1 ? directionsMinute : directionsMinutes)) : ""));
	} else {
		return (minutes + (minutes > 1 ? directionsMinutes : directionsMinute));
	}
}

function PrintCoordinates(decimal, isLatitude, inDegrees) {
	decimal = parseFloat(decimal);
	if (inDegrees) {
		return (isLatitude ? directionsLat : directionsLong ) + decimal.toFixed(6);
	} else {
		var isPositive = (decimal >= 0);
		var direction = isLatitude ? (isPositive ? directionsNorth : directionsSouth) : (isPositive ? directionsEast : directionsWest);
		decimal = Math.abs(decimal);
		var degrees = Math.floor(decimal);
		decimal = (decimal - degrees) * 60;
		var minutes = Math.floor(decimal);
		decimal = (decimal - minutes) * 60;
		var seconds = Math.round(decimal);
		return (degrees + "\u00B0" + (minutes < 10 ? "0" : "") + minutes + "\u0027" + (seconds < 10 ? "0" : "") + seconds + "\u0022" + (degrees || minutes || seconds ? " " + direction : ""));
	}
}

function GetLocale(supportedLocales,param) {
	var key = null;
	if (supportedLocales) {
		var lang = $("meta[name=language]").attr("content");
		while (lang) {
			var re = new RegExp(lang,"i");
			for (var i in supportedLocales) {
				var loc = supportedLocales[i];
				if (loc.search(re) == 0) {
					key = loc;
					break;
				}
			}
			if (key) {
				key = "&" + param + "=" + key;
				break;
			} else {
				lang = lang.substr(0,lang.lastIndexOf("-"));
			}
		}
	}
	return key ? key : "";
}

jQuery.html = function(obj) {
	return jQuery("<div/>").append(jQuery(obj).clone()).html();
};
jQuery.text = function(html) {
	return html.replace(/(<([^>]+)>)/gi, "");
};
jQuery.includeScript = function(file) {
	var tag = '<'+'script type="text/javascript" src="{0}"'+'>'+'<'+'/script'+'>';
	document.write(tag.replace("{0}",file));
};
jQuery.includeStyleSheet = function(file) {
	var tag = '<'+'link type="text/css" rel="stylesheet" href="{0}"'+'/>';
	document.write(tag.replace("{0}",file));
};


// Attach Map Files, must be done before plug-in mappers are loaded
var _glocs = ["en","es","pt","ja","de","fr","it","ru","ca","da","fi","gl","el","eu","nl","nn","no","sv","th"];
var _gcorpkey = "ABQIAAAABPeAB05I9Fh_fp-uBww_LhSoHGg_n29a5rAwh8ymWGslhZTICxSzr_MSSGS1-NKfbaKEC7M0ezH4wg&client=gme-lds";
var _gkeys = {"chqpvuu8338":"ABQIAAAAbm0os9oS0GvjBJ4vRvHT1BQgDwy0DFOQckRqIU3Q4ej9a-vq4RTY1uzmWF3NT1Kp55sb6Vae83LSkg", "chqpvuu8339":"ABQIAAAAbm0os9oS0GvjBJ4vRvHT1BSDXBTkpslkjxqSVbSA6yN1SU2zIBTHwGoTwq7Sc_3C1OjOw0PxRddoow", "10.108.37.54":"ABQIAAAA3VF2PxXAqBCcKDqia2rcChQrLecwRN_EnsDq8xCtAr3FwaK3DRTIB6Ro0CFj-qmOIMY3qxpHPEO3rA", "localhost":"ABQIAAAA3VF2PxXAqBCcKDqia2rcChT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRJ1o2Mb4gqjXJUxUcoPtG7or-zRg", "chqpvuu8529":"ABQIAAAAbm0os9oS0GvjBJ4vRvHT1BSx4hj9GTG13BNB-Gm2eolnvpOsOhRsgK4qq-PeN9zDqJxwbM4JNOn7YA", "10.97.148.90":"ABQIAAAAbm0os9oS0GvjBJ4vRvHT1BTJjMIgrxYX-7XnlzDSBRl9o-5SYhRvg68lPmWRnX64H9893x4RkDe0lw", "10.88.17.82":"ABQIAAAAbm0os9oS0GvjBJ4vRvHT1BTcLxbjXB2tyZw4Ud7ULMk4kWE4uxSoj9p9H0rnuTPMdeSSRxGqXD6W8w"};
$.includeScript("http://maps.google.com/maps?file=api&v=2.131f" + GetLocale(_glocs,"hl") + "&key=" + (window.location.hostname.search(/lds.org/i) >= 0 ? _gcorpkey : _gkeys[window.location.hostname]));

var _velocs = ["en-US","es-US","pt-BR","ja-JP","de-DE","fr-FR","it-IT","en-GB","en-CA","en-AU","en-IN","es-MX","es-ES","pt-PT","fr-CA","cs-CZ","da-DK","fi-FI","nl-NL","nb-NO","sv-SE"];
//$.includeScript("http://" + (window.location.hostname.search(/lds.org/i) >= 0 ? "" : "staging.") + "dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" + GetLocale(_velocs,"mkt"));
$.includeScript("http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" + GetLocale(_velocs,"mkt"));



