﻿
mapEngine = {
	_mapType: 'google',
	_dataPoints: [],
	_markers: [],
	_mapstraction: null,
	_mapstractions: {},
	
	_currentLat: 37.062500,
	_currentLon: -95.677068,
	_currentZoom: 4,
	_currentAltitute: 10000000,
	_isInitialized: false,
	_searchType: 'churches',
	
	_iconUrl: '/js/maps/ChurchIcon.png',
	_iconShadowUrl: '/js/maps/Iconshadow.png',
	
	setMapType: function(mapType) {
		this._mapType = mapType;
	},
	
	initMap: function() {
		//window.onresize = function(e) {	mapEngine.onResize(e);	}
	
		Event.observe(window,'resize',this.onResize.bindAsEventListener(this));
	
		// get main map
		this.map = $('Map');
		
		// get windows		
		this.message = $('Message');
		this.messageContainer = $('MessageContainer');
		
		this.panel = $('Panel');
		this.panelContainer = $('PanelContainer');	
		this.panelTop = $('PanelTop');	
		
		this.hidePanel();
		this.hideMessage();	
	
		this._mapstraction = null;		
		// remove child nodes from Map div
		for (var i=0; i<this.map.childNodes.length; i++) {
			this.map.childNodes[i].style.display = 'none';
		}
		
		// create a div for the map type and hide the other types
		var mapID = 'map_' + this._mapType;
		var innerMap = document.getElementById(mapID);
		
		if (innerMap == null) {		
			var innerMap = document.createElement('div');
			innerMap.setAttribute('id',mapID);
			innerMap.style.width = '845px';
			innerMap.style.height = '445px';
			this.map.appendChild(innerMap);
		} else {
			innerMap.style.display = '';
		}
		
		// create an instance of mapstraction for the map type
		var mapstraction = this._mapstractions[this._mapType];
		
		if (mapstraction == null) {		
			mapstraction = new Mapstraction(mapID, this._mapType);
			// setup default map controls
			mapstraction.addControls({ pan: true, zoom: 'large', overview: false, scale: true, map_type: true });
			this._mapstractions[this._mapType] = mapstraction;
		}
		
		this._mapstraction = this._mapstractions[this._mapType];
		
		// set default position of map
		if (!this._isInitialized) {
			this.setMapPosition();
			this._isInitialized = true;
		}
		
		// initialize google's scroll wheel
		if (this._mapType == 'google') 
			this._mapstraction.maps['google'].enableScrollWheelZoom();
			
		// TEMP
		//this.plotData();
	},

	setMapPosition: function() {
		this._mapstraction.setCenterAndZoom(new LatLonPoint(this._currentLat, this._currentLon), this._currentZoom);
	
		if (this._mapType == 'freeearth') {
			try {
				this._mapstraction.maps['freeearth'].zoomTo(this._altitude, 3, 'easenone');
			} catch (e) {}
		}
	},
	
	query: function(url, location, radius) {
	
		this.hidePanel();
		this.clearMarkers();
	
		this.showMessage('<b>Searching</b><p>Searching for ' + this._searchType + ' within ' + radius + ' miles of "' + location + '"</p>');
	
		if (!this._isInitialized) {
			alert('Please let the page finish loading before searching');
			return;
		}
		
		if (radius <= 10) {
			this._currentZoom = 10;
			this._altitude = 48000;	
		} else if (radius <= 25) {
			this._currentZoom = 9;
			this._altitude = 92000;	
		} else if (radius <= 50) {
			this._currentZoom = 8;
			this._altitude = 250000;	
		} else if (radius <= 200) {
			this._currentZoom = 7;
			this._altitude = 1000000;		
		} else if (radius <= 500) {
			this._currentZoom = 5;
			this._altitude = 5000000;				
		} else {
			this._currentZoom = 4;		
			this._altitude = 100000000;		
		}
	
		// do ajax call
		new Ajax.Request(url,
			{
				method:'get',
				onSuccess: function(transport) {
					
					mapEngine.handleData(transport);
					
					//var response = transport.responseText || "no response text";
					//alert("Success! \n\n" + response);
				},
				onFailure: function() { 
					alert('Something went wrong...') 
				}
			});

	},
	
	handleData: function(resp) {
		
		// clear side panel
		while (this.panel.childNodes.length > 0) 
			this.panel.removeChild(this.panel.childNodes[this.panel.childNodes.length-1]);
			
		var sideList = document.createElement('ul');
		sideList.className = 'sideList';
		this.panel.appendChild(sideList);	
		
		// document
		var xmlDoc = resp.responseXML;
		var minDistance = 25000;
		
		// get new map position		
		var locationData = xmlDoc.documentElement.getElementsByTagName( 'location' );			
		var searchLat = locationData[0].getAttribute( 'lat' );
		var searchLon = locationData[0].getAttribute( 'lon' );
		var usedNearestSearch = (locationData[0].getAttribute( 'usedNearestSearch' ) == 'true');	
		
		// set new location
		this._currentLat = searchLat;
		this._currentLon = searchLon;
		
		// get XML elements		
		var locationElements = xmlDoc.documentElement.getElementsByTagName( 'church' );
		this.panelTop.innerHTML = 'Found ' + locationElements.length.toString() + ' ' + this._searchType;

		// plot points
		for ( var i = 0; i < locationElements.length; i++ ) {
	
			var element = locationElements[i];
			
			// get distance
			var distance = parseInt(element.getAttribute( 'distance' ));				
			if (distance < minDistance)
				minDistance = distance;
			
			// get workplace information			
			name = element.getAttribute( 'name' ); 
			lat = element.getAttribute( 'lat' );
			lon = element.getAttribute( 'lon' );
			address = element.getAttribute( 'address' );
			city = element.getAttribute( 'city' );
			state = element.getAttribute( 'state' );
			zip = element.getAttribute( 'zip' );
			phone = element.getAttribute( 'phone' );
			website = element.getAttribute( 'website' );
			
			// create info bubble to the marker
			var popupHtml = '<div class="popup">' + 
				'<b>' + name + '</b><br />' + 
				address + '<br />' +
				city + ', ' + state + ' ' + zip  +
				((phone != '') ? '<br />' + phone : '') +
				((website != '') ? '<br /><a href="' + website + '">' + website + '</a>' : '');
			
			// add people
			popupHtml += '<ul>';
			var workerElements = element.getElementsByTagName( 'worker' );			
			for (var w=0; w<workerElements.length; w++) {
				popupHtml += '<li>' + workerElements[w].getAttribute( 'firstname' ) + ' ' + workerElements[w].getAttribute( 'lastname' ) + ' - ' + workerElements[w].getAttribute( 'position' );
			}			
			popupHtml += '</ul>' + 
				'</div>';
				
			this.addMarker(i, lat, lon, popupHtml);					
			
			// build side window			
			sideList.innerHTML += 
				'<li>' + 
					'<span class="workplace"><a href="javascript:mapEngine.showMarker(' + i + ');void(0);">' + name + '</a></span><br />' + 
					'<span class="worklocation">' + city + ', ' + state + '</span>' + 
				'</li>';
		}
	
		
		// reset map
		this.setMapPosition();
		
		this.hideMessage();
		this.showPanel();
	},

	
	addMarker: function(i, lat, lon, popupHtml) {
		// create marker
		var marker = new Marker(new LatLonPoint(lat, lon));

		// place marker
		marker.setInfoBubble(popupHtml);
		marker.setIcon(this._iconUrl);	
							
		if (this._mapType == 'google') {
			marker.iconSize = [30.0,34.0];
			marker.iconAnchor = [15.0,34.0];
			marker.iconShadowUrl = this._iconShadowUrl;
			marker.iconShadowSize = [48.0, 34.0];			
		}			
		
		// TODO: shadow for google, not for others!
		this._mapstraction.addMarker(marker); //, {icon: this._iconUrl, iconSize: [30,40], iconAnchor: [15,24]}); //, iconShadow: this._iconShadowUrl, );
		
		this._markers[i] = marker;
	
	},
	
	clearMarkers: function() {
		// clear all existing markers
		for (var i=0; i<this._markers.length; i++) {
			this._mapstraction.removeMarker(this._markers[i]);
		}
		this._markers = [];	
	},
	
	showPanel: function() {
		this.panelContainer.show();
		this.positionPanel();
	},
	
	hidePanel: function() {
		this.panelContainer.hide();
	},	
	
	positionPanel: function() {
		// calculate map position
		var mapPos = this.map.positionedOffset();
		var mapSize = this.map.getDimensions();
		var panelSize = this.panelContainer.getDimensions();
		
		// position overlay based on type
		
		//this.message.style.top = parseInt( mapPos.top + (mapSize.height / 2) - (infoSize.height / 2) ).toString() + 'px';
		
		if (this._mapType == 'yahoo' || this._mapType == 'freeearth') {
			// position on the left side
			this.panelContainer.style.top = (mapPos.top + 10).toString() + 'px';
			this.panelContainer.style.left = (mapPos.left + 10).toString() + 'px';
			
		} else {			
			// position near the right edge
			this.panelContainer.style.top = (mapPos.top + 32).toString() + 'px';
			this.panelContainer.style.left = (mapPos.left + mapSize.width - panelSize.width - 10).toString() + 'px';		
		}						
	},
	
	showMarker: function(i) {
		if (this._mapType == 'microsoft' || this._mapType == 'freeearth') {
			alert('Sorry, you have to click the icon on the map to make this work in ' + this._mapType);
		//} else if (this._mapType == 'freeearth') {
		//	this._markers[i].toFreeEarth().openInfoWindowHtml('test message');
		} else {
			this._markers[i].openBubble();
		}
	},
	
	positionMessage: function() {
		// position and size
		var mapPos = this.map.positionedOffset();
		var mapSize = this.map.getDimensions();
		var infoSize = this.messageContainer.getDimensions();
				
		// set new position
		this.messageContainer.style.zIndex = 10000;
		this.messageContainer.style.position = 'absolute';
		this.messageContainer.style.top = parseInt( mapPos.top + (mapSize.height / 2) - (infoSize.height / 2) ).toString() + 'px';
		this.messageContainer.style.left = parseInt( mapPos.left + (mapSize.width / 2) - (infoSize.width / 2) ).toString() + 'px';
		
	},
	
	showMessage: function(text) {		
		this.message.innerHTML = text;
		this.messageContainer.show();
		this.positionMessage();
		
	},
	
	hideMessage: function() {
		this.messageContainer.hide();
	},
	
	onResize: function(e) {
		this.positionMessage();
		this.positionPanel();
	}
	
}