OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";
POI_MIN_ZOOM = 14;
COVERAGE_MAX_ZOOM = 10;
WMS_URI = "http://www.historicmapworks.com/Earth2/proxy.php";

script_debug = true;


function Earth(){
	
	/** name of the div where map is located */
	this.div_name;
	/** reference of the  */
	this.grmap;
	/** pointer already exist on the map */
	this.pointer_present;
	/** callback for annotate */
	this.click_callback = null;
	/** marker for geo location */
	this.marker;
	/** markers layer */
	this.mark_layer;
	
	/** Keeps track of current OP layers **/	
	this.all_layers;

	/** mirror for min zoom */
	this.all_zoom_min;
	this.all_zoom_max;
	/** reference to a popup window */
	this.popup;
	/** POI visible */
	this.poi_visible;
	/** Last clicked location */
	this.lclick;
	/** Array of the baselayers for OL */
	this.base_layers;

	
	/** google layers */
	this.g;
	this.ghyb;
	this.gsat;
		
	/** enable lat/long display */
	this.show_balloon;
	
	/* Temp placeholder for total found features */
	this.total_found;
	
	/* Temp placeholder for feature message*/
	this.layer_message;
	
	/* Coverage layer */ 
	this.coverage_layer;
	
	/* Coverage visible */
	this.coverage_visible;
	
	/* Historic photos layer */
	this.hPhoto;
	
	/* Is historic photos enabled for viewing */
	this.ishPhoto;
	
	/** =================================== **/

	this.init = function(divid){
		
		try{		
				pointer_present = false;
				all_layers = new Array();		
				all_zoom_min = new Array();
				all_zoom_max = new Array();
				mark_layer = null;
				base_layers = new Array();
				isPoiControlvisible = false;
				show_balloon = false;
				hPhoto = null;
				popup = null;
				ishPhoto = false;
				coverage_visible = false;
				coverage_layer = null;
						
				if(!divid){
					alert("Div name not found.");
					return;
				}		
				div_name = divid;
				place_map();
		
		
		}catch(e){
			alert(e);
		}
	}
	
	this.update = function(){
			grmap.updateSize();
	}
	
	this.onClickEv = function(callBack){
			click_callback = callBack;	
	}
	
	this.addOverlay = function(mid, layer){
		try{
			var added = addOverlay(mid, layer);
			adjustMarker();
			return added;
		} catch(e){
			alert(e);
		}
	}
	
	this.toggleMap = function(mid){
		try{
			toggleMap(mid);
		} catch(e){
			alert(e);
		}				
	}
	
	this.changeOpac = function(mid, percent){
		try{
			changeOpacity(mid, percent);
		}catch(e){
			alert(e);
		}
	}
	
	this.removeAll = function(){
		try{
			remove_overlays();
		}catch(e){
			alert(e);
		}
	}
	
	this.Exist = function(mid){
		try{
			if(!mid) return false;
			return overlay_exists(mid);
		}catch(e){
			alert(e);
		}
	}
	
	this.isVisible = function(mid){
		try{
			if(!mid) return false;
			return overlay_Visible(mid);
		}catch(e){
			alert("Visible error: " + e);
		}
	}
	
	this.raise = function(mid){
			raiseLayer(mid);
	}
		
	this.addPoi = function(){
			ishPhoto = true;
			var retval = enable_hPhoto();	
			adjustMarker();
			return retval;
	}
	
	this.removePoi = function(name){
			ishPhoto = false;
			disable_hPhoto();
	}
	
	this.changeBase = function(name){
			change_base(name);
	}
		
	this.getCurZoom = function(){
			return grmap.getZoom();
	}
	
	this.placeMarker = function(lt, lg, message){
			placeMarker(lt, lg, message);
	}
		
	this.adjustMarker = function(){	
		adjustMarker();
	}
	
	this.coverage = function(){
		return addCoverage();
	}
	
	this.center = function(lg, lt){
		try{
			
			if(!lg || !lt){
				lg = -98.18847298622131;
				lt = 39.774769485295465;
			}
			
			var lonlat = new OpenLayers.LonLat(lg, lt);		
			lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), grmap.getProjectionObject());		
			grmap.setCenter(lonlat, 4);
			
		} catch(e){
			if(script_debug) alert(e);
		}
	}
	
	this.showBalloon = function(val){
			show_balloon = val;
	}
	
	this.lastPointer = function(){
			return lastPointer();
	}
	
	this.viewPhoto = function(val){
		ishPhoto = val;
	}
	
	/************************************************************************************************************/
	this.checkZoomLevel = function(mid){
		return checkZoomLevel(mid);
	}
	
	this.setMinMaxZoom = function(mid){
		setMinMaxZoom(mid);
	}
	
	this.zoomToLevel = function(level) {
			grmap.zoomTo(level);
	}
	/************************************************************************************************************/
	
	
	/** =================================== **/
	
	function place_map(){
		try{
				grmap = new OpenLayers.Map(div_name, {
			                projection: new OpenLayers.Projection("EPSG:900913"),
			                displayProjection: new OpenLayers.Projection("EPSG:4326"),
			                units: "m",
			                maxResolution: 156543.0339,
			                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
		                	maxZoomLevel: 25,
		            	    numZoomLevels: 25,
		            	    controls: [
		                        new OpenLayers.Control.Navigation(),
		                        new OpenLayers.Control.PanZoomBar(),
								//new OpenLayers.Control.LayerSwitcher(),		                        
		                        new OpenLayers.Control.ScaleLine(),
		                        new OpenLayers.Control.MousePosition() 
		                    ], 
		    
			                panMethod: OpenLayers.Easing.Linear.easeOut,
			                panDuration: 10
		
						}
				);
				
				/** Place Layers onto the map **/
				g = new OpenLayers.Layer.Google(
							"Google Maps", 
							{
								sphericalMercator: true,
								numZoomLevels: 25
							}
				);
				
		        ghyb = new OpenLayers.Layer.Google(
		                "Google Hybrid",
		                {
							type: G_HYBRID_MAP, 
							numZoomLevels: 25,
							sphericalMercator: true
						}
		        );
		        gsat = new OpenLayers.Layer.Google(
		                "Google Satellite",
		                {
							type: G_SATELLITE_MAP, 
							numZoomLevels: 25,
							sphericalMercator: true
						}
		        );
				
				// ==================================== //
				base_layers[0] = g;
				base_layers[1] = ghyb;
				base_layers[2] = gsat;
				
				grmap.addLayers(base_layers);
				
				
		        var ddBounds = new OpenLayers.Bounds(-73.839111,40.287907,-68.214111,44.441624);
		        grmap.zoomToExtent(ddBounds.transform(grmap.displayProjection, grmap.getProjectionObject()));					
				grmap.events.register("click", grmap, function(e) { handlePOIClick(e); }); 
							
				grmap.events.register("zoomend", grmap, function(e){					
					mainMap_Listener();
				});
							
		} catch(e){
			if(script_debug) alert(e);
		}
	}  // end of the place map
	
	
	/** Listener for the big map */
	function mainMap_Listener(){		
		if(grmap.getZoom() < POI_MIN_ZOOM && isPoiControlvisible){
			isPoiControlvisible = false;
			try{disable_poi_controls(1);} catch(e){}
			disable_hPhoto();			
		} else if (grmap.getZoom() >= POI_MIN_ZOOM && !isPoiControlvisible){
			isPoiControlvisible = true;
			try{disable_poi_controls(0);} catch(e){}
			enable_hPhoto();			
		}
	}
	
	/** Click handler */
	function handlePOIClick(event){

					layer_message = "";
					total_found = 0;
				
					/** Hidden marker */    	
					var size = new OpenLayers.Size(20,34);
					var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
					var icon = new OpenLayers.Icon("/Earth/icon/aqua.png",size,offset);
				    
				  	var lonlat = grmap.getLonLatFromViewPortPx(event.xy);
					var pLat = lonlat.lat;
					var pLong = lonlat.lon;
				  
				  	var new_center = lonlat;
          		
            
				  	lonlat = lonlat.transform(grmap.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));		
					var lt = lonlat.lat;
					var lg = lonlat.lon;
				    
				    try{ grmap.removeLayer(mark_layer); }catch(err){}
				    
					marker = new OpenLayers.Marker( new OpenLayers.LonLat(pLong, pLat) ,icon);
			        mark_layer =  new OpenLayers.Layer.Markers( "Marker" ); 
					mark_layer.addMarker(marker);			    
			        grmap.addLayer(mark_layer);	

					if(popup != null)
							try{ popup.destroy(); } catch(e){}
					
					if(show_balloon == true){			
									
						popup = new OpenLayers.Popup.FramedCloud(
				               'popup',
				               marker.lonlat,
				               null,
				               "<b>Latitude:</b> " + lt + 
								"<br /><b>Longitude:</b> " + lg,
				               marker.icon,
				               true);
			
				        grmap.addPopup(popup);
			
				        
					} // end show balloon	
					/*
					if(hPhoto == null){
						grmap.setCenter(grmap.getLonLatFromViewPortPx(event.xy));
						if(click_callback != null){
							click_callback(lt, lg);
						}					
						return;
					}
					*/
					if(isPoiControlvisible && ishPhoto)
						getLOCData(lt, lg, marker, event);						
					
					grmap.setCenter(grmap.getLonLatFromViewPortPx(event.xy));
					
					if(click_callback != null){
						click_callback(lt, lg);
					}
					
						
	}	
	
	function getLOCData(lt, lg, marker, event){
				
		var additional_string = "";
		
		if(show_balloon){
		
			additional_string += "<b>Latitude:</b> " + lt + "<br /><b>Longitude:</b> " + lg;
			try{ 
				popup.destroy(); 
				popup = new OpenLayers.Popup.FramedCloud('popup', marker.lonlat, null, additional_string, marker.icon, true);	
				grmap.addPopup(popup);
			} catch(e){}			
			
		}			
				var link = "?REQUEST=GetFeatureInfo" +
						   "&EXCEPTIONS=application/vnd.ogc.se_xml" +
						   "&BBOX=" + grmap.getExtent().toBBOX() + 
						   "&X=" + event.xy.x + 
						   "&Y=" + event.xy.y +
						   "&INFO_FORMAT=text/plain" + 
						   "&FEATURE_COUNT=50" + 
						   "&Styles=" +
						   "&Srs=EPSG:900913" +
						   "&WIDTH=" + grmap.size.w +
						   "&HEIGHT=" + grmap.size.h;
				
				var l = link + "&QUERY_LAYERS=topp:LOC_Buildings&Layers=topp:LOC_Buildings";

		
					
			$.ajax({ 	url: WMS_URI + l, 
				 		cache: false,
				 		dataType: 'html',
				 		async: false,
				 		success:  function(data){
				 				
								var ret = setLOCHTML(data);
								if(!ret) return;
						}		
			});	
		
			if(layer_message.length <  20) return;
			
			try{ popup.destroy();}catch(e){}
			popup = new OpenLayers.Popup.FramedCloud(
	               'popup',
	               marker.lonlat,
	               null,
	               additional_string +
				   "<br /><br /><table border=0>" + layer_message + "</table>",
	               marker.icon,
	               true);
	        grmap.addPopup(popup);

	}
	
	function setLOCHTML(st){
				
				if(st == "no features were found") return 0;		
				var text = st.split("--------------------------------------------");
				var i;		
				if(text.length == 1) return 0;
				
				var answer = "";
				
				var data = text[1].split("\n");		
				$.ajax({ 	
					url: "getLOC.php?p=" + data[1], 
					cache: false,
					dataType: 'html',
					async: false,
					success:  function(data){
						layer_message += data;		
					}
				});	
				
				return 1;
	}
		
	function addOverlay(mid, layerNum){	
		
		try{			
					var extent = null;			
					var collection = "US";
					var layer_name = mid;
								
					if(isNaN(mid)){
							
						collection = mid.substring(0,2);
						mid = mid.substring(2);  
						layer_name = collection + mid;
						
					}

					/************************************************************************************************************/
					//	set min and max zoom in the arrays for this new map
					setMinMaxZoom(mid);	
					
					checkzoom = checkZoomLevel(mid);
					
					//	if the current zoom level is not within the range for this map, 
					//  dont add the overlay and return false (this will cause put_map() to display the error message)
					if (checkzoom != false) {
							
						return false; 
					
					}
					/************************************************************************************************************/

					
					$.ajax({ url: '/Earth/get_extend.php?mid=' + mid + '&col=' + collection, 
							 cache: false,
							 dataType: 'html',
							 async: false,
							 success:  function(data){
							 				 	
							 	if(data.length){
								 	try{
									 	var tmp = data.split("|");
										
									 	if(tmp.length > 3){
										 	extent = new OpenLayers.Bounds(tmp[0], tmp[1], tmp[2], tmp[3]);
										}
									}catch(e){} 
								}
										
							}
										
					});
														
					var new_layer = new OpenLayers.Layer.WMS(
			                    "Map " + layer_name, 
								[
									"http://www.historicmapworks.com/Earth/proxy.php",
									"http://img1.historicmapworks.com/Earth/proxy.php",
									"http://img2.historicmapworks.com/Earth/proxy.php",
									"http://img3.historicmapworks.com/Earth/proxy.php"
								],
			                    {
			                        layers: 'topp:' + layer_name,
			                        styles: '',
			                        srs: 'EPSG:4326',
			                        format: "image/gif",
			                        tiled: 'true',
			                        transparent: "true",
									maxExtent: extent,                       
			                        isBaseLayer: false,
			                        transitionEffect: 'resize',
			                        layerID: layerNum
			                    },
			                    {
			                    	
									buffer: 0					
			                    }
			                );        
			    
					
					
					try{
						/* add layer to array */
						all_layers[layer_name] = new_layer;
						/* add listener for the map */
						addMapListener(layer_name);
					}catch(e){
						alert("Error1: " + e);
					}

					try{		
			    	grmap.addLayer(all_layers[layer_name]);
			    	} catch(e){
						alert("Failed to add layer: " + e);
					}
					
					
					/*
					event = "MapAdd";
					// try to disapath the event 
					//this.dispatchEvent("mapAdd", {customData: "this is a custom event!"}, false);
    				if (document.createEventObject){
				        // dispatch for IE
				        var evt = document.createEventObject();
				        evt.mName = layerNum;
				        this.fireEvent('on'+event,evt);
				        
				    } else{
				        // dispatch for firefox + others
				        var evt = document.createEvent("HTMLEvents");
				        evt.mName = layerNum;				        
				        evt.initEvent(event, true, true ); // event type,bubbling,cancelable
				        this.dispatchEvent(evt);
				    }
    				*/
					
		return true;
			
    
    	} catch(e){
			if(script_debug) alert(e);
		}
		
		
		
	}
	
	/************************************************************************************************************/
	//	sets minimum and maximum zoom in the all_zoom arrays for given mapid, if not already set
	//	called when creating a new overlay and by checkZoomLevel() in case min and max zoom haven't been set yet
	function setMinMaxZoom(mid) {
	
		if(!all_zoom_min[mid] && !all_zoom_max[mid]) {
					
			$.ajax({ url: '/Earth/get_extend.php?mid=' + mid + '&col=US', 
				 cache: false,
				 dataType: 'html',
				 async: false,
				 success:  function(data){
						 				 	
				 	if(data.length){
					 	try{
						 	var tmp = data.split("|");
						
							all_zoom_min[mid] = 0; 
							all_zoom_max[mid] = 0;
							//if(tmp[4] != undefined && tmp[4] != null && tmp[4] != 0 && tmp[5] != undefined && tmp[5] != null && tmp[5] != 0){
							if(typeof tmp[4] != undefined && typeof tmp[5]  != undefined) {
								
								all_zoom_min[mid] = tmp[4];
								all_zoom_max[mid] = tmp[5];
										
							}							
						}catch(e){}
					}
				}		
			
			});
	
		}
	
	}
	
	//	checks if the current zoom level is acceptable for the given mapid
	//	returns false if level is ok, returns "in" or "out" if the level is out of range
	function checkZoomLevel(mid) {
	
		setMinMaxZoom(mid);
	
		var currentzoom = grmap.getZoom();
		// if no data aailable just show the map without limitations
		if(all_zoom_min[mid] == 0 && all_zoom_max[mid] == 0) return false;

		if (currentzoom < all_zoom_min[mid] || currentzoom > all_zoom_max[mid]){	
			if (currentzoom < all_zoom_min[mid]) {
							
				var msg = "in";
						
			} else if (currentzoom > all_zoom_max[mid]) {
							
				var msg = "out";
					
			}
			
			return msg;
	
		} else {
		
			return false;
		
		}
	
	}
	
	//	creates a listener for change in zoom level
	function addMapListener(mid){
			
		grmap.events.register("zoomend", all_layers[mid], function(e){
		
			//if(all_zoom_min[mid] != undefined && all_zoom_min[mid] != null && all_zoom_min[mid] != 0){
			if(typeof all_zoom_min[mid] != undefined && typeof all_zoom_max[mid] != undefined) {
				
				checkzoom = checkZoomLevel(mid);
				
				try{
					var cur = all_layers[mid].getVisibility();
				} catch(e){
					return;
				}
				
				//	if this zoom level is ok, hide the error message (for when the user adds a map, goes outside of allowable range and then back in)
				if (checkzoom == false) { hide_zoom_msg(mid); }
				
				//	if layer isnt visible, don't do anything
				if (!cur) return;
				
				//	if level is out of range, hide the map and display the message "zoom in" or "zoom out" (value of checkzoom)
				if (checkzoom != false) {
					
					try{ hide_map_zoom(mid, checkzoom); }catch(e){}
																																
				}
									
								
			}			
			
		});
		
	}
	/************************************************************************************************************/
	
	
	function toggleMap(mid){
		all_layers[mid].setVisibility(!all_layers[mid].getVisibility());
	}
	
	function changeOpacity(mid, percent){				
		/** raise current map to the top */
		raiseLayer(mid);
		
		// check if layer is visible and exist 
		if(all_layers[mid] != undefined && all_layers[mid] != null && all_layers[mid].getVisibility()){
			all_layers[mid].setOpacity( roundNumber(percent/100, 2)  );
		}
		
		return;
	}
	
	function remove_overlays(){
		for(x in all_layers){
			grmap.removeLayer(all_layers[x]);
		}	
		delete all_layers;
		delete all_zoom_min;
		
		all_layers = new Array();
		all_zoom_min = new Array();
		
	}
	
	function overlay_Visible(mid){
		var val = false;
		
		try{
			val = all_layers[mid].getVisibility();
		}catch(e){
			return false;
		}

		return val;
	}
	
	function overlay_exists(mid){
		if(all_layers[mid] != null && all_layers[mid] != undefined)
			return true;
		return false;
	}
	
	function raiseLayer(mid){
		
		try{
			//grmap.raiseLayer(all_layers[mid], all_layers.length);
			grmap.raiseLayer(all_layers[mid], 100000000)
			
			adjustMarker();
		} catch(e){
			alert("Error: " + e + " Please refresh the browser");
		}

	}
	
	function enable_hPhoto(){
		
		if(!ishPhoto) return;
				
		if(grmap.getZoom() < POI_MIN_ZOOM){
			alert("Please zoom in more to see points of interest.");
			return false;
		}
		
		var style_em = OpenLayers.Util.extend(
			{},
			OpenLayers.Feature.Vector.style['default']
		);
			
			style_em.fillOpacity = 1;
			style_em.fillColor = "#000000";
			style_em.pointRadius = 0;
			style_em.graphicWidth = 20;
			style_em.graphicHeight = 20;
			style_em.externalGraphic = "http://www.historicmapworks.com/Earth/icon/LOC_Buildings.gif";
			
			
			hPhoto = new OpenLayers.Layer.WFS(
		                "Points of Interest: LOC_Buildings", 
		                "http://www.historicmapworks.com/Earth/proxy1.php",
		                {	
							typename: 'topp:LOC_Buildings'
		                },
						{
		                    typename: "LOC_Buildings", 
		                    featureNS: 'http://www.openplans.org/topp',
		                    projection: grmap.displayProjection,
		                    style: style_em
		                }
		    );
                
        		     
        grmap.addLayer(hPhoto);
        return true;
        
        
	}
		
	function disable_hPhoto(){
		try{
			grmap.removeLayer(hPhoto);			
		}catch(e){}
	}	
		
	function change_base(name){
		if(name == 'satellite'){
			grmap.setBaseLayer(base_layers[2]);
		} else if(name == 'street'){
			grmap.setBaseLayer(base_layers[0]);
		} else if(name == 'hybrid'){
			grmap.setBaseLayer(base_layers[1]);
		} else 
			return;
	}

	function placeMarker(lt, lg, message){			
		try{
		var lonlat = new OpenLayers.LonLat(lg, lt);		
		lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), grmap.getProjectionObject());		
			
		/** Hidden marker */    	
		var size = new OpenLayers.Size(20,34);
		var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
		var icon = new OpenLayers.Icon("/Earth/icon/aqua.png",size,offset);	
		  
		try{ 
				/* Clean up earth from all the trash */
			 	marker.destroy(); 
			    grmap.removeLayer(mark_layer); 
		    	mark_layer.destroy();
				popup.destroy();
				
		}catch(err){}	    
			    
		marker = new OpenLayers.Marker( lonlat ,icon);
        mark_layer =  new OpenLayers.Layer.Markers( "Marker" ); 
		mark_layer.addMarker(marker);			    
        grmap.addLayer(mark_layer);	
	

		if(message.length > 1){
			message = "<br /><table border=0>" + message + "</table><br />";
		} else {
			 message = "<br /><b>Latitude:</b> " + lt + "<br /><b>Longitude:</b> " + lg + "<br /><br />";
		}
	
				popup = new OpenLayers.Popup.FramedCloud(
		               'popup',
		               marker.lonlat,
		               null,
		               message,
		               marker.icon,
		               true);
		       	grmap.addPopup(popup);
	
		       	
		grmap.setCenter(lonlat, 17);
		}catch(e){
			alert(e);
		}
	} 
	

	function addCoverage(){	
		
		if(coverage_visible){
			coverage_visible = false;
			coverage_layer.setVisibility(false);
			return false; 
		}
		
		if(coverage_layer != null){
			coverage_visible = true;
			coverage_layer.setVisibility(true);
			return true;
		}
		
		coverage_visible = true;
		coverage_layer = new OpenLayers.Layer.WMS(
                    "World Coverage", 
					[
						"http://www.historicmapworks.com/Earth/proxy.php"
					],
                    {
                        layers: "topp:coverage1",  //GIS_Coverage
                        styles: '',
                        srs: 'EPSG:4326',
                        format: "image/png",
                        tiled: 'true',
                        transparent: "true",                       
                        isBaseLayer: false,
                        transitionEffect: 'resize'
                    },
                    {
                    	
						buffer: 0					
                    }
                ); 
				 
		//COVERAGE_MAX_ZOOM
		grmap.events.register("zoomend", coverage_layer, function(e){
										
			if(grmap.getZoom() >= COVERAGE_MAX_ZOOM && coverage_visible == true){
				removeCoverage(0);							
			}	
			
			if(grmap.getZoom() < COVERAGE_MAX_ZOOM && coverage_visible == false){
				removeCoverage(1);
			}
								
		});
		grmap.addLayer(coverage_layer);
		return true;
	}
	
	function removeCoverage(num){
		
		coverage_layer.setVisibility(num);
		if(num){
			$('#coveragealert').stop().slideUp('fast');
			coverage_visible = true;	
		} else {
			$('#coveragealert').show().animate({opacity: 1.0}, 7000).slideUp('fast');
			coverage_visible = false;
			/* Uncheck checkbox for coverage */
			try{coveageDisabled();} catch(e){}
		}
		
	}
	
	function lastPointer(){
		try{
				try{
					var lonlat = marker.lonlat;
				} catch(e){
					return "";
				}	
				
				lonlat = lonlat.transform(grmap.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));		
				var lt = lonlat.lat;
				var lg = lonlat.lon;
				
				var st = "(" + lt + "%2C " + lg + ")";
		} catch(e){
			if(script_debug) alert(e);
		}
		return st;
	}
	
	
	function adjustMarker(){
		
		grmap.raiseLayer(mark_layer, 1);
		grmap.raiseLayer(mark_layer, all_layers.length);
	}
}