/*
	Extension to prototype library: Class.extend(source,additions)
*/
Object.extend(Class, {
	extend: function(source,additions) {
		var newclass = Class.create();
		if ($C(source)) {
			Object.extend($C(newclass),$C(source));
		}
		Object.extend($C(newclass), additions);
		return newclass;
	}
});

function $C(object) { return object.prototype; }

// enable SVG for firefox / opera
_mSvgEnabled = true;
_mSvgForced  = true;


/* 
	Add an overlays() function
*/	  
GMap2.prototype.overlays = function() {
	return this.O;
}


/*

		DnDMarker class

*/
function DnDMarker(a, b) {
	this.inheritFrom = GMarker;
	this.inheritFrom(a, b);

	this.infoid = new Date().getTime();
	this.info = '';
	
	this.type = 'default';
}

DnDMarker.prototype = GMarker.prototype;

DnDMarker.prototype.bind = function(controller) {
	this.controller = controller;

	try {
		var markerimage = DnD.iconImage(this);
		markerimage.marker = this;

		controller.eventMouseDown = controller.markerMouseDown.bindAsEventListener(controller);
		Event.observe(markerimage, "mousedown", controller.eventMouseDown);

		controller.eventMouseOver = controller.markerMouseOver.bindAsEventListener(controller);
		Event.observe(markerimage, "mouseover", controller.eventMouseOver);

		GEvent.addListener(this, "infowindowclose", function() {
			this.info = $('ta'+this.infoid).value;
		});

	} catch(e) {}
}


/*

		DnDTextMarker class

*/

function DnDTextMarker(point, tooltip) {

	var imageElement = document.createElement('img');
	imageElement.src = 'images/spacer.gif';
	var icon = new DnDIcon(imageElement);

	this.inheritFrom = PdMarker;
	this.inheritFrom(point, icon, tooltip);
	
	this.pane = G_MAP_MARKER_PANE;
	this.allowLeftTooltips(false);
	this.percentOpacity = 100;
	
	this.type = 'text';
}

DnDTextMarker.prototype = PdMarker.prototype;

DnDTextMarker.prototype.bind = function(controller, value) {
	this.setTooltipHiding(false); // never hide tooltip
	this.setTooltip(value);
	this.showTooltip(value);

	this.controller = controller;

	var tooltipObject;
	try {
		tooltipObject = this.tooltipObject;
		tooltipObject.marker = this;

		controller.eventTextMouseDown = controller.markerMouseDown.bindAsEventListener(controller);
		Event.observe(tooltipObject, "mousedown", controller.eventTextMouseDown);

		controller.eventMouseOver = controller.markerMouseOver.bindAsEventListener(controller);
		Event.observe(tooltipObject, "mouseover", controller.eventMouseOver);

		GEvent.bind(controller.map, "moveend", this, this.reZoom);

	} catch(e) {}
}


/*

		DnDPolyLineMarker class

*/
function DnDPolyLineMarker(a,t) {
	var icon = new GIcon()

	if (t) icon.image = '/images/route_image.png';
	icon.shadow = "";
	icon.iconSize = new GSize(10,10);
	icon.shadowSize = new GSize(0, 0);
	icon.iconAnchor = new GPoint(5, 5);
	icon.infoWindowAnchor = new GPoint(5, 5);

	this.inheritFrom = GMarker;
	this.inheritFrom(a, icon);

	this.infoid = new Date().getTime();
	this.info = '';
	
	this.draggable = t;
	
	this.prevline = null;
	this.nextline = null;
	this.prevmarker = null;
	this.nextmarker = null;
	
	this.type = 'poly';
}

DnDPolyLineMarker.prototype = GMarker.prototype;

DnDPolyLineMarker.prototype.bind = function(controller) {
	this.controller = controller;

	try {
		var markerimage = DnD.iconImage(this);
		markerimage.marker = this;

		controller.eventMouseDown = controller.markerMouseDown.bindAsEventListener(controller);
		Event.observe(markerimage, "mousedown", controller.eventMouseDown);
		
		controller.eventMouseOver = controller.markerMouseOver.bindAsEventListener(controller);
		Event.observe(markerimage, "mouseover", controller.eventMouseOver);

	} catch(e) {}
}


/************************************************

		DnDIcon class

*************************************************/
function DnDIcon(imageElement) {
	this.inheritFrom = GIcon;
	this.inheritFrom();

	var thesrc = imageElement.src;
	if (!thesrc) {
		var trythis = imageElement.outerHTML.match(/src='([^']*)',/);	
		thesrc = RegExp.$1;
	} 

	this.image = thesrc;
	
	if (this.image.match(/marker_20/)) {
		this.shadow = "/images/mm_20_shadow.png";
		this.shadowSize = new GSize(22, 20);
	} else if (this.image.match(/marker_34/)) {
		this.shadow = "/images/mm_34_shadow.png";
		this.shadowSize = new GSize(37, 34);
	} else {
		this.shadow = "";
		this.shadowSize = new GSize(0, 0);		
	}
	
	this.iconSize = new GSize(imageElement.clientWidth,imageElement.clientHeight);
	this.iconAnchor = new GPoint(imageElement.clientWidth/2, imageElement.clientHeight/2);
	this.infoWindowAnchor = new GPoint(imageElement.clientWidth/2, imageElement.clientHeight/2);
}

DnDIcon.prototype = GIcon.prototype;


/************************************************

		DnDMapData class

*************************************************/

function DnDMapData() {
	this.paths = [];
	this.markers = {};
	this.currentid = null;
}

DnDMapData.prototype.currentPath = function() {
	return this.paths[this.currentid].points;
}

DnDMapData.prototype.extendPath = function(point) {
	this.paths[this.currentid].points.push(point);
}

DnDMapData.prototype.newPath = function(mode,points) {
	var thepoints = (points) ? points : [];
	this.paths.push({type:mode, points:thepoints});
	this.currentid = this.paths.length-1;
}

DnDMapData.prototype.removePoint = function(point) {

	var pathinfo = this.pointLoc(point);

	var path = this.paths[pathinfo[0]];
	if (path.type == 'scribble') {
		this.paths = this.paths.without(path);
		
		this.newPath('scribble', path.points.slice(0,pathinfo[1]) );
		this.newPath('scribble', path.points.slice(pathinfo[1]+1) );

		this.currentid = this.paths.length-1;	
	} else {	
		var newpoints = path.points.without(point);

		if (newpoints.length == 1) {
			this.paths = this.paths.without(path);
			this.currentid = this.paths.length-1;
		}
		else {
			this.paths[pathinfo[0]].points = newpoints;
			this.currentid = pathinfo[0];
		}	
	}
}

DnDMapData.prototype.pointLoc = function(point) {	
	var pathid = -1;
	var itemid = -1;
	
	this.paths.each(function(path,i) {
		path.points.each(function(p,j) {			
			if (p == point) {
				itemid = j;
				pathid = i;
				return;	
			} 
		});
	});
	return [pathid,itemid];

}

DnDMapData.prototype.addBefore = function(point,prev_point) {
	this.insert(point,prev_point,true);
}

DnDMapData.prototype.addAfter = function(point,next_point) {
	this.insert(point,next_point,false);
}

DnDMapData.prototype.insert = function(point,thepoint,before) {
	var newarray = [];
	this.paths[this.currentid].points.each(function(p) {
		if (before) newarray.push(p);
		if (p == thepoint) {
			newarray.push(point);
		}
		if (!before) newarray.push(p);
	});
	this.paths[this.currentid].points = newarray;
}


DnDMapData.prototype.clear = function() {
	this.paths = [];
	this.markers = {};
	this.currentid = null;
}



/************************************************

		DnD class

*************************************************/

var userAgent = navigator.userAgent.toLowerCase();
var n4=(document.layers);
var n6=(document.getElementById&&!document.all);
var ie=(document.all);
var o6=(userAgent.indexOf("opera") != -1);
var safari=(userAgent.indexOf("safari") != -1);
var msie  = (userAgent.indexOf("msie") != -1) && (userAgent.indexOf("opera") == -1);

var DnD = {

	topLeftPixelToLatLng: function(element,mapElement,map) {
		var pos = Position.cumulativeOffset(element);
		
		return DnD.pixelToLatLng(pos,mapElement,map);

	},

	leftPixelToLatLng: function(element,mapElement,map) {
		var pos = Position.cumulativeOffset(element);
		pos[1] += (element.clientHeight/2);
		
		return DnD.pixelToLatLng(pos,mapElement,map);
	},

	centerPixelToLatLng: function(element,mapElement,map) {
		var pos = Position.cumulativeOffset(element);
		pos[0] += (element.clientWidth/2);
		pos[1] += (element.clientHeight/2)
		
		return DnD.pixelToLatLng(pos,mapElement,map);
	},
	
	pixelToLatLng: function(pos,mapElement,map) {

		var map_pos = Position.cumulativeOffset(mapElement);

		var real_pos = [(pos[0]-map_pos[0]),(pos[1]-map_pos[1])];

		var latlng = map.fromContainerPixelToLatLng(new GPoint(real_pos[0],real_pos[1]));

		return latlng;
		
		// overlay idea from http://koti.mbnet.fi/ojalesa/exam/drag.html
//		var offset = Math.pow(2,(4 - map.getZoom()));
//		return new GLatLng(latlng.y - offset, latlng.x);
	},

	iconImage: function(marker) {
		/* hack since gmaps v2.x removed marker images array */
		var imageElement = marker.cb[0];
//		var imageElement = marker.images[0];

		if (marker.transparentIcon && typeof marker.transparentIcon != "undefined")
			imageElement = marker.transparentIcon;

		return imageElement;
	},

	insideElement: function(pos1,pos2,elem2) {
		return ( (pos2[0] <= pos1[0]) && (pos1[0] < (pos2[0] + elem2.clientWidth))
		       && (pos2[1] <= pos1[1]) && (pos1[1] < (pos2[1] + elem2.clientHeight)) );
	},

	keycode: function(event) {
		var thekeycode;
		if (window.event) thekeycode = window.event.keyCode;
		else if (event) thekeycode = event.which;
		return thekeycode;
	},

	shiftKey: function(event) {
		return (n4) ? e.modifiers & Event.SHIFT_MASK : event.shiftKey;
	},
	
	rightclick: function(event) {
		return ( ( event.button != null && event.button == 2 ) ||
 			 ( event.which != null && event.which == 3 ) );
	},
	
	leftclick: function(event) {
		return ( ( event.button != null && event.button == 1 ) ||
			 ( event.which != null && event.which == 1 ) );
	},
	
	jsdate2mysql: function(datetime) {
		var month = datetime.getMonth() + 1;
		var year = datetime.getYear();
			
		if (!msie) {
			year = Number(year) + 1900;
		}
		
		return year + '-' +
			month + '-' +
			datetime.getDate() + ' ' + 
			datetime.getHours() + ':' +
			datetime.getMinutes() + ':00';
	},

	maptype2num: function(type) {
		if (type == G_HYBRID_MAP) return 0;
		else if (type == G_SATELLITE_MAP) return 1;
		else return 2;
	}
};

var DataUtils = {
	
	markerIcon: function(node) {
		var icon = new GIcon();
		icon.image = node.getAttribute("icon");
		
		if (icon.image.match(/marker_20/)) {
			icon.shadow = "/images/mm_20_shadow.png";
			icon.shadowSize = new GSize(22, 20);
		} else if (icon.image.match(/marker_34/)) {
			icon.shadow = "/images/mm_34_shadow.png";
			icon.shadowSize = new GSize(37, 34);
		} else {
			icon.shadow = "";
			icon.shadowSize = new GSize(0, 0);		
		}		

		icon.iconSize = new GSize(Number(node.getAttribute("width")),Number(node.getAttribute("height")));
		icon.iconAnchor = new GPoint(Number(node.getAttribute("width"))/2, Number(node.getAttribute("height"))/2);
		icon.infoWindowAnchor = new GPoint(Number(node.getAttribute("width"))/2, Number(node.getAttribute("height"))/2);
		return icon;
	
	},
	
	initMapPos: function(xmlDoc, map) {
		var meta = xmlDoc.getElementsByTagName('meta')[0];
	
		var maptype = (meta.getAttribute("maptype")) ? DataUtils.num2maptype(meta.getAttribute("maptype")) : G_NORMAL_MAP;
		map.setCenter(new GLatLng(Number(meta.getAttribute("y")),Number(meta.getAttribute("x"))), 
			      Number(meta.getAttribute("zoom")),
			      maptype);	
	},
	
	getNewLinePoints: function(text) {
		var arr = text.split('),(');
		return arr.collect(function(node) { var tmp = DataUtils.getPolyPoints(node); return new GLatLng(tmp[0],tmp[1]); });
	},
	
	getPolyPoints: function(text) {
		text.match(/^\(?([^,]*),\s*([^\)]*)\)?$/);
		return [Number(RegExp.$1), Number(RegExp.$2)];	
	},
	
	getPoints: function(text) {
		text.match(/^\((.*),\s*(.*)\)$/);
		return [Number(RegExp.$1), Number(RegExp.$2)];	
	},
	
	num2maptype: function(num) {
		if (num == 0) return G_HYBRID_MAP;
		else if (num == 1) return G_SATELLITE_MAP;
		else return G_NORMAL_MAP;
	},
	
	nodeData: function(node) {
		var nodeData;
		if (node.getAttribute("text")) 
			nodeData = node.getAttribute("text");
		else if (node.getAttribute("data")) 
			nodeData = node.getAttribute("data");
		else {
			nodes = node.getElementsByTagName('cont');
			if (nodes.length > 0) nodeData = nodes[0].firstChild.nodeValue;
		}
		
		return nodeData;
	}
};

