// Include the AJAX stylesheet
document.write('<link rel="stylesheet" type="text/css" href="/css/ajax-map.css" />');

// The map number
var mapNumber = getURLParam("map");

// The XMLHttpRequest Objects
var mapRequest = false;    // For map AJAX requests
var infoRequest = false;   // For double click AJAX requests
//var legendRequest = false; // For legend AJAX requests
			
try {
	mapRequest = new ActiveXObject("Msxml2.XMLHTTP");
	infoRequest = new ActiveXObject("Msxml2.XMLHTTP");
	//legendRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
	try {
		mapRequest = new ActiveXObject("Microsoft.XMLHTTP");
		infoRequest = new ActiveXObject("Microsoft.XMLHTTP");
		//legendRequest = new ActiveXObject("Microsoft.XMLHTTP");
	}
	catch (e2) {
		mapRequest = new XMLHttpRequest();
		infoRequest = new XMLHttpRequest();
		//legendRequest = new XMLHttpRequest();
	}
}
			
// The thing holding the map
var holder;
var width, height, xml;

// The map, loading screen
var theMap, loading;
		
// Drag variables
var dragX, dragY;
			
// Extent variables
var extentLeft, extentRight, extentTop, extentBottom, fullExtent, currentScale;

// Scrolling scalebar variables
var scrollerHeight, handleY;

// Permalink
var fromPermalink = false;

// Show a specific business only
var showBusiness = 0;

// Show a specific subcat only
var showSubcat = 0;

/*
 * Sets up the map viewer
 */	
function init() {
	// Get the map placeholder and its dimensions
	holder = document.getElementById("holder");
	getDimensions();

	// Set up the mapping elements
	holder.innerHTML = '<div id="map" style="position: absolute; top: 0; left: 0; border: 1px solid #000000;"></div><div id="watermark"></div><div id="infobar"><div id="scale"></div><div id="copyright"><strong>&copy; Copyright 2006</strong></div></div><div id="loading"><div></div></div><div id="scroller"><div id="scrollerTop"></div><div id="scrollerBottom"></div><div id="zoomIn"></div><div id="zoomOut"></div><div id="handle"><div id="handleScale"></div></div></div><div id="scalebar"><div id="half"></div><div></div></div><div id="panLeft"></div><div id="panRight"></div><div id="panUp"></div><div id="panDown"></div><div id="policyInfo"></div></div>';

	// Get a reference to the map, loading screen
	theMap = document.getElementById("map");
	loading = document.getElementById("loading");

	// Set up dragable elements
	Drag.init(theMap);
				
	// Dragging events
	theMap.onDragStart = mapDragStart;
	theMap.onDrag = mapDrag;
	theMap.onDragEnd = mapDragEnd;
	
	// Mouse event handlers
	theMap.ondblclick = mapDblClick;
	theMap.oncontextmenu = new Function("return false;");
	document.getElementById("zoomIn").onclick = zoomIn;
	document.getElementById("zoomOut").onclick = zoomOut;
	document.getElementById("panLeft").onclick = panLeft;
	document.getElementById("panRight").onclick = panRight;
	document.getElementById("panUp").onclick = panUp;
	document.getElementById("panDown").onclick = panDown;
				
	// Initiate the infobar
	setupInfobar();
	
	// Initiate the scrollbar
	setupScroller();
	
	// Show the loading bar
	loading.style.display = "block";
				
	// Set the image size
	theMap.style.width = width + "px";
	theMap.style.height = height + "px";
				
	var url;
	// Has the user been redirected from a search?
	if (getURLParam("action") == "tocoords") {
		url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=tocoords&x=" + getURLParam("x") + "&y=" + getURLParam("y") + "&layers=all";
		fromPermalink = true;
	}
	// The map is of a specific business
	else if (getURLParam("id") != "") {
		url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=tobusiness&id=" + getURLParam("id") + "&layers=all";
		fromPermalink = true;
		showBusiness = getURLParam("id");
	}
	// If only a specific subcat should be shown
	else if (getURLParam("subcat") != "") {
		url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&subcat=" + getURLParam("subcat") + "&layers=all";
		showSubcat = getURLParam("subcat");
		fromPermalink = true;
	}
	// The default URL
	else {
		url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&layers=all";
		fromPermalink = true;
	}
	sendRequest(url, update);
}

/*
 * Sets a cookie
 */
function setCookie(name, value, expires, path, domain, secure) {
    document.cookie= name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

/*
 * Gets a cookie
 */
function getCookie(name) {
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1) {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    } else {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1) {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}

/*
 * Retrieves GET parameters from the URL
 */
function getURLParam(strParamName) {
	var strReturn = "";
	var strHref = window.location.href;
	if (strHref.indexOf("?") > -1) {
		var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
		var aQueryString = strQueryString.split("&");
		for (var iParam = 0; iParam < aQueryString.length; iParam++) {
			if (aQueryString[iParam].indexOf(strParamName + "=") > -1) {
				var aParam = aQueryString[iParam].split("=");
				strReturn = aParam[1];
				break;
			}
		}
	}
	return strReturn;
}

/*
 * Sets up the info bat that shows the scale etc
 */
function setupInfobar() {
	document.getElementById("infobar").style.width = width + "px";
}

/*
 * Sets up the scroller for zooming in/out
 */
function setupScroller() {
	var handle = document.getElementById("handle");
	var scroller = document.getElementById("scroller");
	
	scrollerHeight = height - 180;
	
	scroller.style.height = scrollerHeight + "px";
	
	Drag.init(handle, null, 0, 0, 0, scrollerHeight - 15);
	handle.onDragStart = handleDragStart;
	handle.onDrag = handleDragging;
	handle.onDragEnd = handleDragEnd;
	
	handle.style.top = scrollerHeight - 15 + "px";
}

/*
 * Records the coordinates at start of map dragging
 */	
function mapDragStart(x, y) {
	dragX = x;
	dragY = y;
}

/*
 * Changes the cursor during mpa dragging
 */
function mapDrag(x, y) {
	theMap.style.cursor = "move";
}

var inProgress = false;

/*
 * Update the map when the user stops dragging it
 */
function mapDragEnd(x, y) {
	theMap.style.cursor = "auto";
			
	if (dragX == x && dragY == y) {
		return;
	}
	
	// Show the loading bar
	loading.style.display = "block";
		
	var clickX = Math.round((theMap.clientWidth/2) - (x));
	var clickY = Math.round((theMap.clientHeight/2) - (y));
				
	// Reload map
	getDimensions();
	var url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=pan&x=" + clickX + "&y=" + clickY + "&left=" + extentLeft + "&right=" + extentRight + "&top=" + extentTop + "&bottom=" + extentBottom + visibleLayers();
	if (showBusiness > 0) {
		url += "&id=" + showBusiness;
	}
	else if (showSubcat > 0) {
		url += "&subcat=" + showSubcat;
	}
	sendRequest(url, update);
}

/*
 * When the user starts zooming in/out with the drag thing
 */
function handleDragStart(x, y) {
	handleY = y;
	
	var range = 200000 - 2500;
		
	// Work out the %age at which the handle ended up
	var percent = (y/(scrollerHeight-15))*100;
		
	// The new scale is the %age of the range + 500
	var scale = Math.round((range/100)*percent)+2500;
		
	document.getElementById("handleScale").innerHTML = "<b>Scale:</b>&nbsp;1:" + scale;
	document.getElementById("handleScale").style.display = "block";
}

/*
 * When the user is zoom in/out with the drag thing
 */
function handleDragging(x, y) {
	// The range is between the full extent and 1:500
	var range = 200000 - 2500;
		
	// Work out the %age at which the handle ended up
	var percent = (y/(scrollerHeight-15))*100;
		
	// The new scale is the %age of the range + 500
	var scale = Math.round((range/100)*percent)+2500;
		
	document.getElementById("handleScale").innerHTML = "<b>Scale:</b>&nbsp;1:" + scale;
}

/*
 * When the user stops zooming in/out with the drag thing
 */
function handleDragEnd(x, y) {
	if (y != handleY) {
		// The range is between the full extent and 1:500
		var range = 200000 - 2500;
		
		// Work out the %age at which the handle ended up
		var percent = (y/(scrollerHeight-15))*100;
		
		// The new scale is the %age of the range + 500
		var scale = Math.round((range/100)*percent)+2500;
	
		// Set the scale
		setscale(scale);
	}
	document.getElementById("handleScale").style.display = "none";
}

/*
 * Gets the width and height of the map display area
 */
function getDimensions() {
	width = holder.clientWidth;
	height = holder.clientHeight;
}

/*
 * Updates the map after an action has been peformed
 */
function update() {
	switch (mapRequest.readyState) {
		case 1:
			// Set the loading bar to 25%
			loading.getElementsByTagName("div")[0].style.width = "75px";
		break;
		case 2:
			// Set the loading bar to 50%
			loading.getElementsByTagName("div")[0].style.width = "150px";
		break;
		case 3:
			// Set the loading bar to 75%
			loading.getElementsByTagName("div")[0].style.width = "225px";
		break;
		case 4:
			// Set the loading bar to 100%
			loading.getElementsByTagName("div")[0].style.width = "300px";
			
			if (mapRequest.status == 200) {
				// Parse the XML
				xml = mapRequest.responseXML;
			
				// Now be really silly by setting a temporary background, hiding the original image, moving it, showing it,
				// and finally removing the temporary image!
				document.getElementById("holder").style.background = "url(" + xml.getElementsByTagName("url")[0].firstChild.nodeValue + ")";
				theMap.style.display = "none";
				theMap.style.background = "url(" + xml.getElementsByTagName("url")[0].firstChild.nodeValue +") no-repeat";
				theMap.style.top = "-1px";
				theMap.style.left = "-1px";
				theMap.style.display = "block";
				document.getElementById("holder").style.backgroundImage = "none";
					
				// Attempt to get the scale
				try {
					document.getElementById("scale").innerHTML = "<b>Scale:</b> 1:" + xml.getElementsByTagName("scale")[0].firstChild.nodeValue;
					currentScale = xml.getElementsByTagName("scale")[0].firstChild.nodeValue;
				}
				catch (e) {
				}
					
				// Get the full extent value
				try {
					fullExtent = 200000;//xml.getElementsByTagName("fullExtent")[0].firstChild.nodeValue;
				}
				catch (e) {
				}
				
				// Attempt to get the distance covered by the map width
				try {
					var distance = xml.getElementsByTagName("distance")[0].firstChild.nodeValue;
					var full = Math.round((distance / width) * 300);
					var half = Math.round((distance / width) * 150)
					
					if (full >= 1000) {
						document.getElementById("scalebar").getElementsByTagName("div")[1].innerHTML = roundNumber(full/1000, 2) + "km&nbsp;";
					}
					else {
						document.getElementById("scalebar").getElementsByTagName("div")[1].innerHTML = full + "m&nbsp;";
					}
					
					if (half >= 1000) {
						document.getElementById("scalebar").getElementsByTagName("div")[0].innerHTML = roundNumber(half/1000, 2) + "km&nbsp;";
					}
					else {
						document.getElementById("scalebar").getElementsByTagName("div")[0].innerHTML = half + "m&nbsp;";
					}
				}
				catch (e) {
				}
					
				extentTop = xml.getElementsByTagName("top")[0].firstChild.nodeValue;
				extentRight = xml.getElementsByTagName("right")[0].firstChild.nodeValue;
				extentBottom = xml.getElementsByTagName("bottom")[0].firstChild.nodeValue;
				extentLeft = xml.getElementsByTagName("left")[0].firstChild.nodeValue;
				
				// Hide the loading bar
				loading.style.display = "none";
				loading.getElementsByTagName("div")[0].style.width = "0";
				
				// Did the user visit via a permalink?
				if (fromPermalink) {
					// Work out where the handle should be on the scroller
					var range = 200000 - 2500;
					var percent = (currentScale - 2500)/range;
					var position = Math.round((height-195) * percent);
					
					document.getElementById("handle").style.top = position + "px";
					
					fromPermalink = false;
				}
			}
			else {
				alert("Error: " + mapRequest.status);
			}
		break;
	}
}

/*
 * Rounds a number to the specified decimal places
 */
function roundNumber(num, places) {
	var newnumber = Math.round(num * Math.pow(10, places)) / Math.pow(10, places);
	return newnumber;
}

/*
 * Sets the scale of the map
 */
function setscale(scale) {
	// Show the loading bar
	loading.style.display = "block";
	
	var url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=setscale&scale=" + scale + "&left=" + extentLeft + "&right=" + extentRight + "&top=" + extentTop + "&bottom=" + extentBottom + visibleLayers();
	if (showBusiness > 0) {
		url += "&id=" + showBusiness;
	}
	else if (showSubcat > 0) {
		url += "&subcat=" + showSubcat;
	}
	sendRequest(url, update);
}

/*
 * Performs a policy search on double click
 */
function mapDblClick(e) {
	var x, y;
				
	// IE doesn't use the same event model
	if (!e)
		var e = window.event;
				
	// Get the coordinates
	if (e.pageX || e.pageY) {
		x = e.pageX - holder.offsetLeft;
		y = e.pageY - holder.offsetTop;
	}
	else if (e.clientX || e.clientY) {
		x = e.clientX - holder.offsetLeft;
		y = e.clientY - holder.offsetTop;
	}
	
	var url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=policyinfo&x=" + x + "&y=" + y + "&left=" + extentLeft + "&right=" + extentRight + "&top=" + extentTop + "&bottom=" + extentBottom + visibleLayers();
	if (showBusiness > 0) {
		url += "&id=" + showBusiness;
	}
	else if (showSubcat > 0) {
		url += "&subcat=" + showSubcat;
	}
	infoRequest.open("GET", url, true);
	infoRequest.onreadystatechange = policyInfo;
	infoRequest.send(null);
}

/*
 * Displays the results of a policy search
 */
function policyInfo() {
	if (infoRequest.readyState == 4 && infoRequest.status == 200) {
		// Parse the XML
		xml = infoRequest.responseXML;
		
		var policies = "";
		var elements = xml.getElementsByTagName("item");
		for(var i=0; elements[i]; i++) {
			policies += "<li>" + elements[i].firstChild.nextSibling.firstChild.nodeValue;
			if (elements[i].lastChild.firstChild.nodeValue != "") {
				policies += " - <a href=\"http://www.visitmold.com/english/businessdetail_map.asp?id=" + elements[i].firstChild.firstChild.nodeValue + "\" target=\"_top\">[More Info]</a>";
			}
			policies += "</li>";
		}
		if (policies == "") {
			policies = "<li>No businesses were found at the specified location!</li>";
		}
		var policyInfo = document.getElementById("policyInfo");
		policyInfo.innerHTML = '<div class="handle"><img src="/images/interface/cancel.gif" alt="Close" style="float: right; cursor: pointer;" onclick="hideResults();" /><img src="/images/interface/information.gif" alt="" /> Business Results</div><div class="padded"><h3>Results:</h3><ul>' + policies + '</ul></div>';
		policyInfo.style.display = "block";
		opacity("policyInfo", 0, 100, 500);
	}
}

/*
 * Hides the results of a policy search
 */
function hideResults() {
	// Fade the results out
	opacity("policyInfo", 100, 0, 500);
	// Then hide them when they're done fading :)
	setTimeout("document.getElementById(\"policyInfo\").style.display = \"none\"", 500);
	theMap.style.cursor = "auto";
}

/*
 * Hides the "first time" message
 */
function hideFirstTime() {
	opacity("firstTime", 100, 0, 500);
	setTimeout("document.getElementById(\"firstTime\").style.display = \"none\"", 500);
}

/*
 * Fades the specified object in/out
 */
function opacity(id, opacStart, opacEnd, millisec) {
	//speed for each frame
	var speed = Math.round(millisec / 100);
	var timer = 0;

	//determine the direction for the blending, if start and end are the same nothing happens
	if(opacStart > opacEnd) {
		for(i = opacStart; i >= opacEnd; i--) {
			setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed));
			timer++;
		}
	}
	else if(opacStart < opacEnd) {
		for(i = opacStart; i <= opacEnd; i++) {
			setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed));
			timer++;
		}
	}
}

/*
 * Change the opacity for different browsers
 */
function changeOpac(opacity, id) {
	var object = document.getElementById(id).style;
	object.opacity = (opacity / 100);
	object.MozOpacity = (opacity / 100);
	object.KhtmlOpacity = (opacity / 100);
	object.filter = "alpha(opacity=" + opacity + ")";
}

/*
 * Zoom in to the next pre-defined scale
 */
function zoomIn() {
	var scales = new Array( 100000, 75000, 50000, 25000, 10000, 5000, 2500);
	
	// Loop through the scales and test to see which comes next
	for (var i=0; i<scales.length; i++) {
		if (currentScale > scales[i]) {
			setscale(scales[i]);
			
			// Work out where the handle should be on the scroller
			var range = 200000 - 2500;
			var percent = (scales[i] - 2500)/range;
			var position = Math.round((height-195) * percent);
			document.getElementById("handle").style.top = position + "px";
			break;
		}
	}
}

/*
 * Zoom out to the next pre-defined scale
 */
function zoomOut() {
	var scales = new Array(5000, 10000, 25000, 50000, 75000, 100000, 200000);
	
	// Loop through the scales and test to see which comes next
	for (var i=0; i<scales.length; i++) {
		if (currentScale < scales[i] && scales[i] <= 200000) {
			setscale(scales[i]);
			
			// Work out where the handle should be on the scroller
			var range = 200000 - 2500;
			var percent = (scales[i] - 2500)/range;
			var position = Math.round((height-195) * percent);
			document.getElementById("handle").style.top = position + "px";
			break;
		}
	}
}

/*
 * The following 4 functions handle the panning button onclick events
 */
function panLeft() {
	moveMap(width/2, "left", 300);
}
function panRight() {
	moveMap(width/2, "right", 300);
}
function panUp() {
	moveMap(height/2, "up", 300);
}
function panDown() {
	moveMap(height/2, "down", 300);
}

/*
 * The next three functions are for moving the map when the user clicks on a pan button,
 * and then updating the map as appropriate
 */
function moveMap(distance, direction, time) {
	// How often should it move?
	var interval = Math.round(time/distance);
	
	for(var i=1; i <= distance; i++) {
		setTimeout("setMapPosition(" + i + ",'" + direction + "')",(interval * i));
	}
	
	setTimeout("mapMoved()", (time+200)); // Leave 200ms extra just in case
}

function setMapPosition(position, direction) {
	switch(direction) {
		case "left":
			theMap.style.left = position + "px";
			break;
		case "right":
			theMap.style.left = -position + "px";
			break;
		case "up":
			theMap.style.top = position + "px";
			break;
		case "down":
			theMap.style.top = -position + "px";
			break;
	}
}

function mapMoved() {
	// Show the loading bar
	loading.style.display = "block";
	
	var clickX = Math.round((theMap.clientWidth/2) - (theMap.offsetLeft));
	var clickY = Math.round((theMap.clientHeight/2) - (theMap.offsetTop ));
				
	// Reload map
	getDimensions();
	var url = "/map_xml.aspx?map=" + mapNumber + "&width=" + width + "&height=" + height + "&action=pan&x=" + clickX + "&y=" + clickY + "&left=" + extentLeft + "&right=" + extentRight + "&top=" + extentTop + "&bottom=" + extentBottom + visibleLayers();
	if (showBusiness > 0) {
		url += "&id=" + showBusiness;
	}
	else if (showSubcat > 0) {
		url += "&subcat=" + showSubcat;
	}
	sendRequest(url, update);
}

/*
 * This function sends a request for the URL, then runs the function specified
 */
function sendRequest(url, func) {
	mapRequest.open("GET", url, true);
	mapRequest.onreadystatechange = func;
	mapRequest.send(null);
}

/*
 * This function works out which layers should be displayed
 */
function visibleLayers() {
	var layerString = "";
	
	return layerString;
}

/*
 * The layers to be displayed have changed...
 */
function layerChanges() {
	setscale(currentScale);
}

/*
 * This checks that the browser really has resized - FF has a bug that fires the onresize event
 * after opening a tab and switching to the old one, or when closing a tab and switching to the old one!
 */
function checkResize() {
	var newWidth = holder.clientWidth;
	var newHeight = holder.clientHeight;
	
	if (Math.abs(height - newHeight) > 1 || Math.abs(width - newWidth) > 1) {
		init();
	}
}
			
window.onload = init;
window.onresize = checkResize;