var CurrentZoom=1.0;
var MaximumZoom=4.0;
var MinimumZoom=1.0;
var ZoomIncrement=1.25;

var ZoomDecrement=1/ZoomIncrement;

var ZoomFactor=1.0/MaximumZoom;

// The following map extent globals are defined in the template or elsewhere:
var MapLatitudeExtentNorth;
var MapLatitudeExtentSouth;
var MapLongitudeExtentWest;
var MapLongitudeExtentEast;

var AbsoluteImagesDirectory="/resources/static/images/GeographicalSearch";

var areaMouseOverEnabled=true;

function getImagesDirectory() {
	return siteRoot+"/.."+AbsoluteImagesDirectory;
}

var AreaTypeID;
var OverlayImage;
var MapImage;
var MapWindow;
var MapMessage;
var MapWindowWidth;
var MapWindowHeight;

var MouseDownPosition=null;
var MouseDownScrollPosition=null;
var Moving=false;
var CurrentCursor="default";


function initGeographicalSearch() {
	OverlayImage=document.getElementById("OverlayImage");
	MapImage=document.getElementById("MapImage");
	MapWindow=document.getElementById("MapWindow");
	MapMessage=document.getElementById("MapMessage");
	MapWindowWidth=parseInt(MapWindow.style.width);
	MapWindowHeight=parseInt(MapWindow.style.height)
	initAreas();
	initImages();
	setMouseWheelEventMethod(OverlayImage,wheel);
	setMouseWheelEventMethod(MapWindow,stopPropagation); // need to do this because firefox doesn't capture the mouse wheel events on the the hidden OverlayImage (during refresh method), resulting in scrolling.
	initPan(OverlayImage);
	var maps=document.getElementsByTagName("map");
	for (i=0; i<maps.length; i++) {
		var map=maps[i];
		setMouseWheelEventMethod(map,wheel) // required for Opera
		initPan(map); // required for Firefox and Opera
	}
}

function initZoom() {
	var p_latitudeCentre=getQueryStringValue("LatCentre");
	var p_longitudeCentre=getQueryStringValue("LongCentre");
	var p_latitudeAngularExtent=getQueryStringValue("LatExt");
	var p_longitudeAngularExtent=getQueryStringValue("LongExt");
	if (!p_latitudeAngularExtent || !p_longitudeAngularExtent) return;
	
	var MapLatitudeCentre=(MapLatitudeExtentNorth+MapLatitudeExtentSouth)/2;
	var MapLatitudeAngularExtent=MapLatitudeExtentNorth-MapLatitudeExtentSouth;
	var MapLongitudeCentre=(MapLongitudeExtentEast+MapLongitudeExtentWest)/2;
	var MapLongitudeAngularExtent=MapLongitudeExtentEast-MapLongitudeExtentWest;
	var ZoomMargin=1.2; // margin to leave around area specified in parameters

	MapImage.style.visibility="hidden";
	try {
		var latitudeZoom=MapLatitudeAngularExtent/p_latitudeAngularExtent;
		var longitudeZoom=MapLongitudeAngularExtent/p_longitudeAngularExtent;
		var zoom=latitudeZoom<longitudeZoom ? latitudeZoom : longitudeZoom;
		setZoom(zoom/ZoomMargin);
	} catch (ex) {}
	if (p_latitudeCentre) try {setCentreTop(MapImage.originalHeight*(-1*(p_latitudeCentre-MapLatitudeCentre)/MapLatitudeAngularExtent+0.5));} catch (ex) {}
	if (p_longitudeCentre) try {setCentreLeft(MapImage.originalWidth*((p_longitudeCentre-MapLongitudeCentre)/MapLongitudeAngularExtent+0.5));} catch (ex) {}
	MapImage.style.visibility="visible";
}

function getMap(areaTypeID) {
	return document.getElementById("Map_"+areaTypeID);
}

function initAreas() {
	var geographicMapContainer=document.getElementById("GeographicMapContainer");
	var areas=geographicMapContainer.getElementsByTagName("area");
	for (i=0; i<areas.length; i++) {
		var area=areas[i];
		area.title=area.alt;
		if (area.addEventListener) {
			area.addEventListener('mouseover',areaMouseOver,false);
			area.addEventListener('mouseout',areaMouseOut,false);
			area.addEventListener('click',areaClick,false);
		} else {
			area.onmouseover=areaMouseOver;
			area.onmouseout=areaMouseOut;
			area.onclick=areaClick;
		}
		area.trueCoords=area.coords.split(",");
	}
}

function initImages() {
	var images=MapWindow.getElementsByTagName("img");
	for (i=0; i<images.length; i++) initImage(images[i]);
}

function initImage(image) {
	image.originalHeight=image.getAttribute("height");
	image.originalWidth=image.getAttribute("width");
	image.originalTop=getPixels(image.style.top);
	image.originalLeft=getPixels(image.style.left);
}

function getPixels(distance) {
	if (!distance) return 0;
	return parseInt(distance,10);
}

function initPan(element) {
	if (element.addEventListener) {
		element.addEventListener('mousedown', panMouseDown, false);
		element.addEventListener('mousemove', panMouseMove, false);
		element.addEventListener('mouseup', panMouseUp, false);
	} else {
		element.onmousedown = panMouseDown;
		element.onmousemove = panMouseMove;
		element.onmouseup = panMouseUp;
	}
}

function setMouseWheelEventMethod(element,method) {
	if (element.addEventListener) {
		element.addEventListener('DOMMouseScroll',method,false); // Firefox
		element.addEventListener('mousewheel',method,false); // Opera/IE
	} else {
		element.onmousewheel=method;
	}
	if (element==window) document.onmousewheel=method;
}

// Mouse Wheel code from http://adomas.org/javascript-mouse-wheel/
function wheel(event) {
	var delta = 0;
	if (!event) event = window.event;
	if (event.wheelDelta) {
		delta = event.wheelDelta/120;
		if (window.opera) delta = -delta;
	} else if (event.detail) {
		delta = -event.detail/3;
	}
	if (delta) handleWheel(event,delta);
	stopPropagation(event);
}

function handleWheel(event,delta) {
	if (delta > 0)
		setZoom(CurrentZoom*ZoomIncrement);
	else
		setZoom(CurrentZoom*ZoomDecrement);
}

function setZoom(zoom) {
	if (zoom<MinimumZoom) {
		zoom=MinimumZoom;
	} else if (zoom>MaximumZoom) {
		zoom=MaximumZoom;
	}
	if (zoom!=CurrentZoom) refresh(zoom);
}

function panMouseDown(event){
	if (!event) event = window.event;
	MouseDownPosition=getMousePosition(event,MapWindow);
	MouseDownScrollPosition=getScrollPosition(MapWindow);
	WasMoving=false;
}

function panMouseMove(event){
	if (!event) event = window.event;
	if (MouseDownPosition) {
		var mousePosition=getMousePosition(event,MapWindow);
		if (mousePosition.x!=MouseDownPosition.x || mousePosition.y!=MouseDownPosition.y) {
			Moving=true;
			OverlayImage.style.cursor="move";
			var mousePosition=getMousePosition(event,MapWindow);
			MapWindow.scrollTop=MouseDownScrollPosition.y-mousePosition.y+MouseDownPosition.y;
			MapWindow.scrollLeft=MouseDownScrollPosition.x-mousePosition.x+MouseDownPosition.x;
		}
	}
	stopPropagation(event);
}

function panMouseUp(event){
	if (!event) event = window.event;
	MouseDownPosition=null;
	if (Moving) {
		Moving=false;
		WasMoving=true;
		OverlayImage.style.cursor=CurrentCursor;
		stopPropagation(event);
	}
}

function areaMouseOver() {
	if (!areaMouseOverEnabled) return;
	areaHighlight(this.id);
	setMapMessage(this.id);
	CurrentCursor="pointer";
	if (!Moving) OverlayImage.style.cursor=CurrentCursor;
}

function areaMouseOut() {
	areaUnhighlight(this.id);
	clearMapMessage(this.id);
	CurrentCursor="default";
	if (!Moving) OverlayImage.style.cursor=CurrentCursor;
}

function stopPropagation(event) {
	if (event.preventDefault) {
		event.preventDefault();
		event.stopPropagation();
	} else {
		event.returnValue = false;
		event.cancelBubble = true;
	}
}

function getScrollPosition(element) {
	var position=new Object();
	position.x=element.scrollLeft;
	position.y=element.scrollTop;
	return position;
}

function getMousePosition(event,element) {
	// note this returns completely different results for IE and Mozilla when called from a scroll event inside a scrollable area.
	if (!element.offsets) {
		element.offsets = getPagePosition(element);
		element.offsets.x += (document.documentElement.scrollLeft || document.body.scrollLeft);
		element.offsets.y += (document.documentElement.scrollTop || document.body.scrollTop);
	}
	var position=new Object();
	position.x=(event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)) - element.offsets.x;
	position.y=(event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) - element.offsets.y;
	return position;
}

function getPagePosition(element) {
	var valueT = 0, valueL = 0;
	var el = element;
	do {
		valueT += el.offsetTop  || 0;
		valueL += el.offsetLeft || 0;
		if (el.offsetParent==document.body) if (element.style.position=='absolute') break; // Safari fix
	} while (el = el.offsetParent);
		el = element;
		do {
		valueT -= el.scrollTop  || 0;
		valueL -= el.scrollLeft || 0;
	} while (el = el.parentNode);
	var position=new Object();
	position.x=valueL;
	position.y=valueT;
	return position;
}

function refresh(newZoom) {
	var centreLeft=getCentreLeft();
	var centreTop=getCentreTop();
	if (newZoom) CurrentZoom=newZoom;
	var images=MapWindow.getElementsByTagName("img");
	for (i=0; i<images.length; i++) {
		var image=images[i];
		image.previousVisibility=image.style.visibility;
		image.style.visibility="hidden";
		refreshImagePosition(image);
		var imageSizeFactor=CurrentZoom*ZoomFactor;
		image.width=image.originalWidth*imageSizeFactor;
		image.height=image.originalHeight*imageSizeFactor;
	}
	setCentreLeft(centreLeft);
	setCentreTop(centreTop);
	for (i=0; i<images.length; i++) {
		var image=images[i];
		image.style.visibility=image.previousVisibility;
	}
	var areas=getMap(AreaTypeID).getElementsByTagName("area");
	for (i=0; i<areas.length; i++) {
		var area=areas[i];
		var areaTrueCoords=area.trueCoords;
		var coords=new Array(areaTrueCoords.length);
		for (x=0; x<coords.length; x++) coords[x]=Math.round(areaTrueCoords[x]*CurrentZoom*ZoomFactor); // need to round because of bug in opera join function.
		area.coords=coords.join(",");
	}
}

function refreshImagePosition(image) {
	var imageSizeFactor=CurrentZoom*ZoomFactor;
	image.style.top=(image.originalTop*imageSizeFactor)+"px";
	image.style.left=(image.originalLeft*imageSizeFactor)+"px";
}

function getOriginalWidth(image) {
	if (!image.originalWidth) image.originalWidth=image.getAttribute("width");
	return image.originalWidth;
}

function getOriginalHeight(image) {
	if (!image.originalHeight) image.originalHeight=image.getAttribute("height");
	return image.originalHeight;
}

function getCentreLeft() {
	return (MapWindow.scrollLeft+MapWindowWidth/2)/(CurrentZoom*ZoomFactor);
}

function setCentreLeft(centreLeft) {
	MapWindow.scrollLeft=centreLeft*CurrentZoom*ZoomFactor-MapWindowWidth/2;
}

function getCentreTop() {
	return (MapWindow.scrollTop+MapWindowHeight/2)/(CurrentZoom*ZoomFactor);
}

function setCentreTop(centreTop) {
	MapWindow.scrollTop=centreTop*CurrentZoom*ZoomFactor-MapWindowHeight/2;
}
