/**
 * @author flathers
 */
dojo.require("esri.map");
dojo.require("esri.tasks.geometry");
dojo.require("dojo.parser");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.TitlePane");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.BorderContainer");
dojo.addOnLoad(init);

var myMap;
var handlers = []; //dojo event handlers
var timer;  //Resize timer prevents immediate resize in IE
var configFile = 'config.xml';
var baseMapDisplayName, baseMapURL, baseMapToggle, baseMapTopLayer, baseMapOpacity;
var searchCapability, geometryURL, searchURL, searchWidth;
var token = '';
var initialExtent;
var services = []; //Services array helps with visibility of layers in dynamic services
var tocScroll = false;
var metadataRedirector = "";
var lineHeight;

function setConfigFile() {
	var node = dojo.byId('config');
	var val = '';
	if (node != null)
		val = node.innerHTML;
	if (val != '')
		configFile = val;

	var href = window.location.href;
	var re = new RegExp("\\?config=([^\\&]*)");
	val = re.exec(href);
	//console.log('val:' + val);
	if (val != '' && val != null)
		configFile = RegExp.lastParen;
	//console.log(configFile);
}

function zoomer() {
	var key = dijit.byId('autoSelect').getDisplayedValue();
	key = key.replace("'", "''"); //Escape apostrophes, just for you, Coeur D'alene
	var queryTask = new esri.tasks.QueryTask(geometryURL);
	addHandler(queryTask, "onComplete", "showResults");
    query = new esri.tasks.Query();
    query.returnGeometry = true;
	query.text = key;
	queryTask.execute(query);
}

function showResults(results) {
	//console.log('finished query');
	var features = results.features;
	var feature = features[0];
	var geometry = feature.geometry;
	var extent = geometry.getExtent();
	myMap.setExtent(extent, true);
}

function initSearch() {
	var autoStore = new dojo.data.ItemFileReadStore({ url: searchURL });
	var filteringSelect = new dijit.form.FilteringSelect({
		id: "autoSelect",
		name: "auto",
		pageSize: 6,
		searchAttr: "Val",
		searchDelay: 500,
		store: autoStore,
		value: ""
	}, "autoSelect");
	filteringSelect.domNode.style.width = searchWidth;
	dojo.byId('search').style.visibility='visible';
}

function init() {
	var testChar = dojo.byId('testChar');
	lineHeight = (testChar.offsetHeight);
	testChar.style.visibility = 'hidden';

	setConfigFile();
	getConfig();
	if(searchCapability == true)
		initSearch();

	

	//move the zoom slider to the right side of the map
	esriConfig.defaults.map.slider = { right:"10px", top:"30px", height:"50%"};
/*
	//These are good settings but we need to know more about them to use them well
	esriConfig.defaults.map.panDuration = 1500;
	esriConfig.defaults.map.panRate = 10;
	esriConfig.defaults.map.zoomDuration = 1500;
	esriConfig.defaults.map.zoomRate = 10;
*/	
	//set up the map
	myMap = new esri.Map("mapDiv");

	var layer = new esri.layers.ArcGISTiledMapServiceLayer(baseMapURL);

	layer.id = 'baseMap';
	if(baseMapTopLayer)
		layer.opacity = baseMapOpacity;
	myMap.addLayer(layer);
	
	setPageElementSizes();

	if (myMap.loaded)
		initMap();
	else
		addHandler(myMap, "onLoad", "initMap");
}

function getConfig() {
	token = getToken();
	
	var xmlDoc = getXMLDoc(configFile);
	var nodes;

	nodes = xmlDoc.getElementsByTagName('title');
	var title = nodes[0].childNodes[0].nodeValue;
	document.title = title;
	dojo.byId('cTitle').innerHTML = title;

	nodes = xmlDoc.getElementsByTagName('metadataRedirector');
	metadataRedirector = nodes[0].childNodes[0].nodeValue;

	nodes = xmlDoc.getElementsByTagName('baseMap');
	baseMapDisplayName = nodes[0].getElementsByTagName('displayName')[0].childNodes[0].nodeValue;
	baseMapURL = nodes[0].getElementsByTagName('URL')[0].childNodes[0].nodeValue;
	baseMapToken = nodes[0].getElementsByTagName('tokenRequired')[0].childNodes[0].nodeValue;
	baseMapOpacity = nodes[0].getElementsByTagName('opacity')[0].childNodes[0].nodeValue;
	if (baseMapToken == 'true')
		baseMapURL += '?token=' + token;
	//showText(baseMapURL);
	baseMapToggle = nodes[0].getElementsByTagName('toggle')[0].childNodes[0].nodeValue;
	if (baseMapToggle == 'true')
		baseMapToggle = true;
	else
		baseMapToggle = false;
	baseMapTopLayer = nodes[0].getElementsByTagName('topLayer')[0].childNodes[0].nodeValue;
	if (baseMapTopLayer == 'true')
		baseMapTopLayer = true;
	else
		baseMapTopLayer = false;
	services[services.length] = new serviceInfo(baseMapDisplayName, baseMapURL, 'baseMap', true, false);
	
	nodes = xmlDoc.getElementsByTagName('initialExtent');
	if (nodes[0].getElementsByTagName('xmin')[0].childNodes.length) {
		var xmin = parseFloat(nodes[0].getElementsByTagName('xmin')[0].childNodes[0].nodeValue);
		var ymin = parseFloat(nodes[0].getElementsByTagName('ymin')[0].childNodes[0].nodeValue);
		var xmax = parseFloat(nodes[0].getElementsByTagName('xmax')[0].childNodes[0].nodeValue);
		var ymax = parseFloat(nodes[0].getElementsByTagName('ymax')[0].childNodes[0].nodeValue);
		initialExtent = new esri.geometry.Extent(xmin, ymin, xmax, ymax);
	}
	
	//search parameters
	nodes = xmlDoc.getElementsByTagName('search');
	searchCapability = nodes[0].getElementsByTagName('capability')[0].childNodes[0].nodeValue;
	if (searchCapability == 'true') {
		searchCapability = true;
		searchWidth = nodes[0].getElementsByTagName('width')[0].childNodes[0].nodeValue;
		geometryURL = nodes[0].getElementsByTagName('geometryURL')[0].childNodes[0].nodeValue;
		var tokenRequired = nodes[0].getElementsByTagName('tokenRequired')[0].childNodes[0].nodeValue;
		if (tokenRequired == 'true') 
			geometryURL += '?token=' + token;
		searchURL = nodes[0].getElementsByTagName('searchURL')[0].childNodes[0].nodeValue;
		searchURL += '?dataSource=' + nodes[0].getElementsByTagName('dataSource')[0].childNodes[0].nodeValue;
		searchURL += '&UID=' + nodes[0].getElementsByTagName('UID')[0].childNodes[0].nodeValue;
		searchURL += '&PWD=' + nodes[0].getElementsByTagName('PWD')[0].childNodes[0].nodeValue;
		searchURL += '&database=' + nodes[0].getElementsByTagName('database')[0].childNodes[0].nodeValue;
		searchURL += '&keyColName=' + nodes[0].getElementsByTagName('keyColName')[0].childNodes[0].nodeValue;
		searchURL += '&valColName=' + nodes[0].getElementsByTagName('valColName')[0].childNodes[0].nodeValue;
		searchURL += '&tableName=' + nodes[0].getElementsByTagName('tableName')[0].childNodes[0].nodeValue;
		//console.log(geometryURL);
		//console.log(searchURL);
	}
	else
		searchCapability = false;
}

function initMap() {
	if (initialExtent)
		myMap.setExtent(initialExtent);
	AdjustMapSizeHandler();
	addServices();
	addHandler(window, "onresize", "AdjustMapSizeHandler");
	addHandler(myMap, "onUnload", "unloadHandler");
	//addHandler(myMap, "onMouseMove", "getCoords");
}

function serviceInfo(displayName, serviceURL, layerID, checked, showLayers) {
	this.displayName = displayName;
	this.serviceURL = serviceURL;
	this.layerID = layerID;
	this.checked = checked;
	this.showLayers = showLayers;
	this.visibility = [];
}

function addServices(){
	var xmlDoc = getXMLDoc(configFile);
	var nodes = xmlDoc.getElementsByTagName('service');
	if(nodes.length > 0)
		for (var i = 0; i < nodes.length; i++)
			addService(nodes[i], i==nodes.length-1);  //i == nodes.length-1 -> boolean value: is this the last layer to be added?
	else
		buildTOC();
}

function addService(service, lastLayer){
	var displayName = service.getElementsByTagName('displayName')[0].childNodes[0].nodeValue;
	var serviceURL = service.getElementsByTagName('URL')[0].childNodes[0].nodeValue;
	var tokenRequired = service.getElementsByTagName('tokenRequired')[0].childNodes[0].nodeValue;
	var serviceType = service.getElementsByTagName('serviceType')[0].childNodes[0].nodeValue;
	var imageFormat = service.getElementsByTagName('imageFormat')[0].childNodes[0].nodeValue;
	var showLayers = service.getElementsByTagName('showLayers')[0].childNodes[0].nodeValue;
	if (showLayers == 'true')
		showLayers = true;
	else
		showLayers = false;

	var visible = service.getElementsByTagName('visible')[0].childNodes[0].nodeValue;
	var layerID = getID(serviceURL);

	if (tokenRequired == 'true') {
		serviceURL += '?token=' + token;
		//showText(serviceURL);
	}
	
	switch(serviceType) {
		case 'tiled':
			layer = new esri.layers.ArcGISTiledMapServiceLayer(serviceURL);
			break;
		case 'dynamic':
			layer = new esri.layers.ArcGISDynamicMapServiceLayer(serviceURL);
			break;
		case 'image':
			var imageServiceParameters = new esri.layers.ImageServiceParameters();
			imageServiceParameters.format = imageFormat;
			layer = new esri.layers.ArcGISImageServiceLayer(serviceURL,{ imageServiceParameters:imageServiceParameters });
			break;
	}

	layer.id = layerID;

	var checked = '';
	if (visible == 'false')
		layer.hide();
	else
		checked = 'checked';

	myMap.addLayer(layer);
	services[services.length] = new serviceInfo(displayName, serviceURL, layerID, checked, showLayers);

	if(lastLayer)
		addHandler(layer, 'onLoad', 'checkLoaded');
		
	//Keep the base map layer on top
	if(baseMapTopLayer)
		myMap.reorderLayer('baseMap', myMap.layerIds.length)
}

//When all layers are loaded, build the TOC
function checkLoaded() {
	for (var i = 0; i < myMap.layerIds.length; i++) {
		var layer = myMap.getLayer(myMap.layerIds[i]);
		if (!layer.loaded) {
			addHandler(layer, 'onLoad', 'checkLoaded');
			return;
		}
	}

	buildTOC();
}

function buildTOC() {
	var tocText = '';
	var layerCount = myMap.layerIds.length;
	var i;

	if (baseMapToggle)
		tocText = "<input type='checkbox' class='list_item' checked id='baseMap' onClick='toggleServiceVisibility(-1);' /><label for='baseMap'>" + baseMapDisplayName + "</label><br />\n<br />";

	var modifier = 0;
	if(baseMapTopLayer)
		modifier = -1;
	
	for (i = layerCount - 1; i > 0; i--) {
		var layer = myMap.getLayer(myMap.layerIds[i+modifier]);
		if (layer) {

			var service = services[i];
			tocText += "<a href=\"" + service.serviceURL + "\" target=_blank><img class=mlink src=\"images/05.jpg\" alt=\"View Metadata\" /></a><input type='checkbox' class='list_item' " + service.checked + " id='" + service.layerID + "' onClick='toggleServiceVisibility(" + i + ");' /><label for='" + service.layerID + "'>" + service.displayName + "&nbsp;&nbsp;&nbsp;</label><br />\n";
			
			if (!layer.tileInfo && service.showLayers) {
				var infos = layer.layerInfos, info;
				for (var j = 0, il = infos.length; j < il; j++) {
					info = infos[j];
					var checked = '';
					if (info.defaultVisibility) {
						checked = 'checked';
						service.visibility[service.visibility.length] = j;
					}
					var layerURL = service.serviceURL.replace('MapServer', 'MapServer' + "/" + j);
					tocText += "<a href=\"" + metadataRedirector + layerURL + "\" target=_blank><img class=mlink src=\"images/05.jpg\" alt=\"View Metadata\" /></a>&nbsp;&nbsp;&nbsp;<input type='checkbox' class='list_item' " + checked + " onClick='toggleLayerVisibility(" + i + "," + j +");' /><label for='" + info.name + "'>" + info.name + "&nbsp;&nbsp;&nbsp;</label><br />\n";
				}
			}
		}
	}
	
	var lineCount = tocText.match(/<br \/>/g).length;
	if (lineCount < 6) lineCount = 6;
	var h = lineCount * (lineHeight + 6);
	//console.log(lineCount + ', ' + lineHeight + ', ' + h)

	if (h > dojo.byId("border2").clientHeight)
		h = dojo.byId("border2").clientHeight;
	//console.log(h + ', ' + dojo.byId("border2").clientHeight)

	var container = dijit.byId("border2");
	
	var tocPane = new dijit.TitlePane({id:"tocPane", region:"leading", title:"Map Layers", style:"height:" + h + "px; width:300px; overflow-y:auto;z-index:5000;white-space:nowrap;float:left;position:relative;"});
	
	tocText = '<div id="tocText">' + tocText + '</div>';
	
	tocPane.setContent(tocText);
	dijit.byId('border2').addChild(tocPane);

	//Hide the loading message window
	var busyIndicator = dojo.byId('busyIndicator').style.visibility='hidden';
}

function getXMLDoc(path) {
	var xmlDoc;
	try {
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
	} 
	catch (e) {
		try {
			xmlDoc = document.implementation.createDocument("", "", null);
		} 
		catch (e) {
			alert(e.message);
			return;
		}
	}
	xmlDoc.async = false;
	xmlDoc.load(path);
	return xmlDoc;
}

function getToken(){
	var hostname = window.location.hostname;

	if (token)
		return token;
		
	var xmlDoc = getXMLDoc('..//tokens//tokens.xml');
	var nodes = xmlDoc.getElementsByTagName('host');
	for (var i = 0; i < nodes.length; i++) {
		if (nodes[i].nodeType == 1) {
			var host = nodes[i].getElementsByTagName('hostname')[0].childNodes[0].nodeValue;
			if (host == hostname)
				token = nodes[i].getElementsByTagName('token')[0].childNodes[0].nodeValue;
		}
	}
	return token;
}

function toggleServiceVisibility(serviceID) {
	var modifier = 0;
	if(baseMapTopLayer)
		modifier = -1;

	if (serviceID == -1)
		var service = myMap.getLayer('baseMap');
	else
		var service = myMap.getLayer(myMap.layerIds[serviceID+modifier]);
	if (service.visible)
		service.hide();
	else
		service.show();
}

function toggleLayerVisibility(serviceID, layerID) {
	var modifier = 0;
	if(baseMapTopLayer)
		modifier = -1;

	var service = myMap.getLayer(myMap.layerIds[serviceID+modifier]);
	var visibility = services[serviceID].visibility;
	var found=false;

	for (i = 0; i < visibility.length; i++) {
		if (visibility[i] == layerID) {
			visibility.splice(i, 1);
			found = true;
		}
	}
	if (!found)
		visibility[visibility.length] = layerID;
	service.setVisibleLayers(visibility);
}

// function to set initial sizes of page elements
function setPageElementSizes() {
	if (document.documentElement) {
		document.documentElement.style.overflow = "hidden";
		document.documentElement.style.height = "100%";
		document.documentElement.style.width = "100%";
	} else {
		document.body.style.overflow = "hidden";
		document.body.style.height = "100%";
		document.body.style.width = "100%";
	}  
}

// handler for window resize
function AdjustMapSizeHandler() {
	var mapDiv = dojo.byId("mapDiv");
	var headerDiv = dojo.byId("header");

    //get browser window dimensions 
	var viewPort = dijit.getViewport();
    var sHeight = viewPort.h;
	var sWidth = viewPort.w;

    // calc dimensions needed for map
    var mHeight = sHeight - headerDiv.clientHeight;
    mapDiv.style.height = mHeight + 'px';
    mapDiv.style.width = sWidth + 'px';

	//if(dojo.byId('toc').innerHTML != '')
	//	fixTOCSize();

	//clear any existing resize timer
	clearTimeout(timer);
    //create new resize timer with delay of 500 milliseconds
    timer = setTimeout(function() { myMap.resize(); }, 500);
}

//Dynamic sizing & scrollbar for TOC pane
function fixTOCSize() {
	var headerDiv = dojo.byId("header");
	var tocNode = dojo.byId("toc");
	var helpPane = dojo.byId("helpPane");
	var viewPort = dijit.getViewport();
    var sHeight = viewPort.h;
	var h = sHeight - headerDiv.clientHeight - (helpPane.clientHeight * 2) - 1;
	if (h > tocNode.clientHeight + helpPane.clientHeight && tocNode.clientHeight > 0)
		h = tocNode.clientHeight + helpPane.clientHeight;

	var tocText = tocNode.innerHTML.toLowerCase();
	var lineCount = tocText.split('<br>').length - 1;
	var lineHeight = lineCount * 1.75;
	
	tocNode.parentNode.parentNode.parentNode.style.overflowY = 'auto';
	tocNode.parentNode.parentNode.parentNode.style.overflowX = 'hidden';
	//	tocNode.parentNode.parentNode.parentNode.style.height = h + 'px'; //commented out 20090415 -- in testing, it looks like TOC height works automatically correctly in both IE and FF?

	var leftMenu = dojo.byId('leftMenu');
	//Adjust TOC width for presence of scroll bar in FF.
	//Only works with standard windows scroll bar width right now.
	var sH = tocNode.parentNode.parentNode.parentNode.scrollHeight;
	var cH = tocNode.parentNode.parentNode.parentNode.clientHeight;
	if (sH > cH) {
		//scrollbar is there
		tocScroll = true;
		var w = tocNode.parentNode.parentNode.parentNode.clientWidth + 30;
		tocNode.parentNode.parentNode.parentNode.style.width = w + 'px';
	}
	else {
		if (tocScroll) {
			var w = tocNode.parentNode.parentNode.parentNode.clientWidth - 14;
			tocNode.parentNode.parentNode.parentNode.style.width = w + 'px';
		}
		tocScroll = false;
	}

	//IE kludge, for now
	if (navigator.appName == 'Microsoft Internet Explorer') {
		var leftMenu = dojo.byId('leftMenu');
		leftMenu.style.width = '25%';
	}

	//var d = new Date();
	//showText(d.getSeconds());
}

function getID(url) {
	var id = "";
	var urlParts = url.split("/");
	var ubound = urlParts.length - 1;

	if (urlParts[ubound].toLowerCase() == 'mapserver')
		id = urlParts[ubound-1];
	else
		id = urlParts[ubound-1] + '/' + urlParts[ubound];
	return id;
}

function addHandler(object, event, call) {
	handlers[handlers.length] = dojo.connect(object, event, call);
}

//To avoid memory leaks, you should remove listeners when the application is being closed
function unloadHandler() {
	for(var i = 0; i < handlers.length; i++)
		dojo.disconnect(handlers[i]);
}

function showText(msg) {
	var text = dojo.byId('text');
	text.innerHTML = msg;
	console.log(msg);
}
