/*
*	@class: View
*	wraps the UI and exposes methods to access UI elements
*/
function View()
{
	/*
	*	@property: View.CONSTANTS
	*	const values
	*/
	this.CONSTANTS = {
		MAP_CENTER_LAT : 42.2000,
		MAP_CENTER_LNG : -72.1419,
		ZOOM_INDEX : 7,
		CHECKBOX_CLICKED : 0,
		TOWN_LEVEL_ZOOM_INDEX : 11,
		RESTRICTION_TEXT : "*May not accept items from <span style='color:#ff0000'>NON-RESIDENTS</span>*<br>*Call for up to date information*"
	};

	/*
	*	@property: View.markerGroups
	*	collections of different types of markers, used to toggle visibility of markers on the map
	*/
	this.markerGroups = {
		"R_Battery" : [],
		"R_Lamp" : [],
		"R_Therm" : [],
		"R_Elec" : [],
		"R_Other" : [],
		"B_Battery" : [],
		"B_Lamp" : [],
		"B_Therm" : [],
		"B_Elec" : [],
		"B_Other" : [],
		"ALL" : []
	};
	
	/*
	*	@property: View.checkboxes	
	*	handles for UI checkboxes
	*/
	this.checkboxes = [
		{name : 'R_Battery', el : document.getElementById('cb_res_bat')}, 
		{name : 'R_Lamp', el : document.getElementById('cb_res_lamp')}, 
		{name : 'R_Therm', el : document.getElementById('cb_res_therm')}, 
		{name : 'R_Elec', el : document.getElementById('cb_res_elec')}, 
		{name : 'R_Other', el : document.getElementById('cb_res_other')}, 
		{name : 'B_Battery', el : document.getElementById('cb_bus_bat')}, 
		{name : 'B_Lamp', el : document.getElementById('cb_bus_lamp')}, 
		{name : 'B_Therm', el : document.getElementById('cb_bus_therm')}, 
		{name : 'B_Elec', el : document.getElementById('cb_bus_elec')}, 
		{name : 'B_Other', el : document.getElementById('cb_bus_other')}
	];	
	
	/*
	*	@property: View.selects
	*	handles for UI select elements
	*/	
	this.selects = [
		{name : 'sel_towns', el : document.getElementById('sel_towns')}
	];	
	
	/*
	*	@property: View.buttons	
	*	handles for UI buttons
	*/
	this.buttons = [		
		{name : 'selectAllCheckboxes', el : document.getElementById('but_selectAllCheckboxes') },
		{name : 'map_refresh', el : document.getElementById('but_mapRefresh') },
		{name : 'map_enlarge', el : document.getElementById('but_mapEnlarge') },
		{name : 'map_minimize', el : document.getElementById('but_minimizeMap') }		
	];
	
	/*
	*	@property: View.dragableObject	
	*	handle for a UI element with click and drag capability using YUI
	*/
	this.dragableObject = new YAHOO.util.DD("gmapContainer"); 
	this.dragableObject.setHandleElId("mapheader"); 
			
	this.mapHeader = document.getElementById("mapheader");
	this.mapContainerElement = document.getElementById("gmapContainer");
	this.mapElement = document.getElementById("gmap");
	this.map;
	
	this.icon1 = new GIcon();	
	this.icon2 = new GIcon();	
	this.icon3 = new GIcon();	
	this.icon4 = new GIcon();		
	
	this.icons = {
		residential : new GIcon(), 
		commercial : new GIcon(), 
		shadow: new GIcon()
	}
		
	this.icons.shadow.image = "images/icon_shadow.png";
	this.icons.shadow.iconSize = new GSize(15, 15);
	this.icons.shadow.shadowSize =  new GSize(22, 20);	
		
	this.icons.residential.image = "images/red.png";
	this.icons.residential.shadow = "images/icon_shadow.png";
	this.icons.residential.iconSize = new GSize(15, 15);
	this.icons.residential.shadowSize =  new GSize(22, 20);		
	
	this.icons.commercial.image = "images/both.png";
	this.icons.commercial.shadow = "images/icon_shadow.png";
	this.icons.commercial.iconSize = new GSize(15, 15);
	this.icons.commercial.shadowSize =  new GSize(22, 20);
		
	/* 
	*	@property: View.observers
	*	observers of this View object 
	*/
	this.observers = new Array();
	
	/* 
	*	@method: View.addObserver
	*	add an object as an observer to the observer collection
	*/
	this.addObserver =function(o){ this.observers.push(o);  }
	
	/*
	*	@method: View.notifyObservers
	*	notify all observers when an event is dispatched
	*/	
	this.notifyObservers = function(EVENT)
	{
		for(var i =0; i<this.observers.length; i++)
			this.observers[i].notify(EVENT);					
	}			
							
	/*
	*	@method: View.loadMap
	*	create and init a GMap, then overlay markers for each of the given sites
	*/
	this.loadMap = function(sites) { 		
		 if (GBrowserIsCompatible()) { 
			//create map
	        this.map = new GMap2(this.mapElement, {mapTypes:[G_NORMAL_MAP,G_SATELLITE_MAP,G_PHYSICAL_MAP]});
			
			//add controls to map
			this.map.addControl(new GLargeMapControl());
			this.map.addControl(new GMapTypeControl());							
			this.map.addControl(new GOverviewMapControl());
			this.map.enableScrollWheelZoom();
			var pos = new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(20, 30)); 
			this.map.addControl(new GScaleControl(), pos);			
			
			//this.map.obj = this;			

			GEvent.addListener(this.map, "move", this.checkBounds);
			
			var minMapScale = 7; 
			var maxMapScale = 16; 
			var maxTerrainMapScale = 15;
			
			// overwrite getMinimumResolution() and getMaximumResolution() methods for each map type 
			var mapTypes = this.map.getMapTypes(); 
			for (var i=0; i<mapTypes.length; i++) { 
				if(mapTypes[i].getName() == "Terrain")
				{
					mapTypes[i].getMinimumResolution = function() {return minMapScale;} 
					mapTypes[i].getMaximumResolution = function() {return maxTerrainMapScale;} 
				}else{
					mapTypes[i].getMinimumResolution = function() {return minMapScale;} 
					mapTypes[i].getMaximumResolution = function() {return maxMapScale;} 
				}
			}

			// set map defaults, x,y center, zoom index, maptype(roads, satellite, hybrid view)
	        this.map.setCenter(new GLatLng(this.CONSTANTS.MAP_CENTER_LAT, 
																this.CONSTANTS. MAP_CENTER_LNG), 
																this.CONSTANTS.ZOOM_INDEX);			
			this.map.setMapType(G_PHYSICAL_MAP);
					
			// add a new GMarker for each site
			for(var i in sites)
			{				
				var point = new GLatLng(sites[i].lat,sites[i].lng); 			
				var com = sites[i].isCommercial();
				var res = sites[i].isResidential();			
				var sitetype = 0;
				
				if(res == 1){ sitetype = 2; }
				if(com == 1){ sitetype = 1; } 	
		
				if(sitetype == 0) continue;
				var marker = this.createMarker(point, sitetype, sites[i]);				
				this.addToMarkerGroups(marker, sites[i]);
				this.map.addOverlay(marker);						
				marker.hide();
			}	
		}	  
	}
		
	/*
	*	@method: View.checkBounds
	*	Checks whether there are GMarkers in the view, if not zoom out until there are.
	*/
	this.checkBounds = function()
	{
		var allowedBounds = new GLatLngBounds(new GLatLng(40,-73.5), new GLatLng(44,-69.8));
				
        if (allowedBounds.containsLatLng(this.getCenter()))  return;
     
        var C = this.getCenter();
        var X = C.lng();
        var Y = C.lat();

        var AmaxX = allowedBounds.getNorthEast().lng();
        var AmaxY = allowedBounds.getNorthEast().lat();
        var AminX = allowedBounds.getSouthWest().lng();
        var AminY = allowedBounds.getSouthWest().lat();

        if (X < AminX) {X = AminX;}
        if (X > AmaxX) {X = AmaxX;}
        if (Y < AminY) {Y = AminY;}
        if (Y > AmaxY) {Y = AmaxY;}
       this.setCenter(new GLatLng(Y,X));
	}
		
	/*
	*	@method: View.addToMarkerGroups
	*	adds a GMarker to the markerGroups they belong in
	*/
	this.addToMarkerGroups = function(marker, site)
	{
		if(site.R_Battery == "Y" || site.R_Battery == "F") this.markerGroups.R_Battery.push(marker);
		if(site.R_Lamps == "Y" || site.R_Lamps == "F") this.markerGroups.R_Lamp.push(marker);
		if(site.R_Thermostats == "Y" || site.R_Thermostats == "F") this.markerGroups.R_Therm.push(marker);
		if(site.R_ElectronicDevs == "Y" || site.R_ElectronicDevs == "F") this.markerGroups.R_Elec.push(marker);
		if(site.R_OtherHgProducts == "Y" || site.R_OtherHgProducts == "F") this.markerGroups.R_Other.push(marker);
		if(site.B_Battery == "Y" || site.B_Battery == "F") this.markerGroups.B_Battery.push(marker);
		if(site.B_Lamps == "Y" || site.B_Lamps == "F") this.markerGroups.B_Lamp.push(marker);
		if(site.B_Thermostats == "Y" || site.B_Thermostats == "F") this.markerGroups.B_Therm.push(marker);
		if(site.B_ElectronicDevs == "Y" || site.B_ElectronicDevs == "F") this.markerGroups.B_Elec.push(marker);
		if(site.B_OtherHgProducts == "Y" || site.B_OtherHgProducts == "F") this.markerGroups.B_Other.push(marker);		
		this.markerGroups.ALL.push(marker);
	}
		
	/*
	*	@method: View.createMarker
	*	return a GMarker for a site, at the given point, with the icon determined by sitetype.
	*	creating the GMarker includes scripting the bubble's inner html
	*/
	this.createMarker = function(point, sitetype, site){ 	

		var theIcon;
		
		switch(sitetype)
		{	
			case 1:	theIcon = this.icons.commercial; break;
			case 2: 	theIcon = this.icons.residential; break;
			case 3:	theIcon = this.icons.commercial; break;
			case 0: 	theIcon = null; break;
			default: 	theIcon = this.icons.commercial; break;
		}	
			
		theIcon.iconAnchor = new GPoint(6, 20);
		theIcon.infoWindowAnchor = new GPoint(5, 1);		
		
		var marker = new GMarker(point, theIcon); 	 
		
		var bubbleString = "";
		if(site.sitename != "") bubbleString += "<div id='bubble'><div class='bubbleText'><span class='bubbleBold'>Sitename: </span>" +site.name + "</div>";		
		
		var addressArray = new Array();
		if(site.address1.length > 0 ) addressArray.push(site.address1);
		if(site.address2.length > 0 ) addressArray.push(site.address2);
		if(site.address3.length > 0 ) addressArray.push(site.address3);
		address = addressArray.join(", ");	

		if(address != "") bubbleString += "<div class='bubbleText'><span class='bubbleBold'>Address: </span>" + address + "</div>";		
		if(site.city != "") bubbleString += "<div class='bubbleText'><span class='bubbleBold'>City: </span>" + site.city + "</div>";
		
		var hours =  site.day + " " + site.hours;		
		if(hours.length > 1) bubbleString += "<div class='bubbleText'><span class='bubbleBold'>Hours: </span>" + hours + "</div>";
		if(site.phone != "") bubbleString += "<div class='bubbleText'><span class='bubbleBold'>Phone: </span>" + site.phone + "</div>";
		
		bubbleString +="<br/><div class='bubbleListContainer'>";
		bubbleString +="<div class='bubbleList'>";
		bubbleString +="<div class='bubbleListHeader_noBorder'>Residential</div><div class='bubbleListHeader_Border'>Items Accepted</div>";
		bubbleString +="<ul>";

		if(site.R_Battery == "Y" || site.R_Battery == "F") {bubbleString +="<li>Batteries</li>"; }
		if(site.R_Lamps == "Y" || site.R_Lamps == "F") {bubbleString +="<li>Lamps</li>"; }
		if(site.R_Thermostats == "Y" || site.R_Thermostats == "F") {bubbleString +="<li>Thermostats</li>"; }
		if(site.R_ElectronicDevs == "Y" || site.R_ElectronicDevs == "F") {bubbleString +="<li>Electronic Devices</li>"; }
		if(site.R_OtherHgProducts == "Y" || site.R_OtherHgProducts == "F") {bubbleString +="<li>Other Products</li>"; }	
		
		bubbleString +="</ul>";
		bubbleString +="</div>";
		bubbleString +="<div class='bubbleList'>";
		bubbleString +="<div class='bubbleListHeader_noBorder'>Commercial</div><div class='bubbleListHeader_Border'>Items Accepted</div>";
		bubbleString +="<ul>";
		
		if(site.B_Battery == "Y" || site.B_Battery == "F") { bubbleString +="<li>Batteries</li>"; }
		if(site.B_Lamps == "Y" || site.B_Lamps == "F") {bubbleString +="<li>Lamps</li>"; }
		if(site.B_Thermostats == "Y" || site.B_Thermostats == "F") {bubbleString +="<li>Thermostats</li>"; }
		if(site.B_ElectronicDevs == "Y" || site.B_ElectronicDevs == "F") {bubbleString +="<li>Electronic Devices</li>"; }
		if(site.B_OtherHgProducts == "Y" || site.B_OtherHgProducts == "F") {bubbleString +="<li>Other Products</li>"; }
		
		bubbleString +="</ul>";
		bubbleString +="</div>";		
		bubbleString +="</div>";		

		if(site.comments != "") bubbleString += "<div class='bubbleText'><span class='bubbleBold'>Comments: </span>" + site.comments + "</div>";	
		
		// this line was replaced with the following line when the datasource for the restriction text in the bubble was changed to the excel spreadsheet from a hardcoded const string in Model 
		//if(site.restrictions != "") bubbleString += "<div class='bubbleText'>" + this.CONSTANTS.RESTRICTION_TEXT + "</div>";
		if(site.restrictions != "") bubbleString += "<div class='bubbleText'>" + site.restrictions.replace("******", "***<br/>***") + "</div>";
		
		bubbleString +="</div>";
				
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml( bubbleString
			);  
		});  	
		
		GEvent.addListener(marker, "mouseover", function() {
			marker.openInfoWindowHtml( bubbleString
			);  
		});  	
		
		return marker;
	}
	
	/*
	*	@method: View.getSelectedItems
	*	return an array containing ids of the selected checkboxes in the map header
	*/
	this.getSelectedItems = function()
	{
		var selectedItems = new Array();		
		for(var i in this.checkboxes)		
			if(this.checkboxes[i].el.checked) selectedItems.push(this.checkboxes[i].name);		
		
		return selectedItems;
	}
	
	/*
	*	@method: View.update
	*	update the map with a new set of sites
	*/
	this.update = function(selectedItems, townCoordinates)
	{		
		//hide all GMarkers
		this.clearMapMarkers();
		
		//map item values to markergroup arrays, if the item value exists in selectedItems, show all markers in the array
		var itemsAndMarkers = [
			{item : 'R_Battery', markers : this.markerGroups.R_Battery },
			{item : 'R_Lamp', markers : this.markerGroups.R_Lamp },
			{item : 'R_Therm', markers : this.markerGroups.R_Therm },
			{item : 'R_Elec', markers : this.markerGroups.R_Elec },
			{item : 'R_Other', markers : this.markerGroups.R_Other },
			{item : 'B_Battery', markers : this.markerGroups.B_Battery },
			{item : 'B_Lamp', markers : this.markerGroups.B_Lamp },
			{item : 'B_Therm', markers : this.markerGroups.B_Therm },
			{item : 'B_Elec', markers : this.markerGroups.B_Elec },
			{item : 'B_Other', markers : this.markerGroups.B_Other }		
		];
		
		for(var i in selectedItems)		
			for(var j in itemsAndMarkers)		
				if(selectedItems[i] == itemsAndMarkers[j].item)			
					for(var k in itemsAndMarkers[j].markers) itemsAndMarkers[j].markers[k].show();
						
		this.zoomToTown(townCoordinates);
	}

	/*
	*	@method: View.clearMapMarkers
	*	hide all markers on the map
	*/	
	this.clearMapMarkers = function()
	{
		for(var i in this.markerGroups.ALL)		
			this.markerGroups.ALL[i].hide();		
	}
	
	/*
	*	@method: View.enlargeMap
	*	enlarges the div element that contains the gmap
	*/
	this.enlargeMap = function()
	{
		var mapCenter = this.map.getCenter();
		var mapDivWidth = document.body.clientWidth - 100;
		var mapDivHeight = 480;		
		var mapDivLeft = 50;
		var mapDivTop = this.mapElement.style.top;		
		this.mapHeader.style.display = "block";
		this.mapContainerElement.style.height = mapDivHeight + 'px';
		this.mapContainerElement.style.width = mapDivWidth + 'px';		    
		this.mapContainerElement.style.position = 'absolute';
		this.mapContainerElement.style.top = mapDivTop;
		this.mapContainerElement.style.left = mapDivLeft + 'px';
		this.mapContainerElement.style.visibility =  'visible';
		
		this.map.checkResize();		
		this.recenterMap(mapCenter);
	}
	
	/*
	*	@method: View.minimizeMap
	*	minimizes the element that contains the map	
	*/
	this.minimizeMap = function()
	{
		var mapCenter = this.map.getCenter();
		var mapDivWidth = '100%';
		var mapDivHeight = 550;
		var mapDivLeft = '';
		var mapDivTop = '';		
		this.mapHeader.style.display = "none";
		this.mapContainerElement.style.height = mapDivHeight + 'px';
		this.mapContainerElement.style.width = mapDivWidth;		    
		this.mapContainerElement.style.position = '';
		this.mapContainerElement.style.top = mapDivTop;
		this.mapContainerElement.style.left = mapDivLeft;
		this.mapContainerElement.style.visibility =  'visible';
		
		this.map.checkResize();			
		this.recenterMap(mapCenter);
	}
		
	/*
	*	@method View.selectAllCheckboxes
	*	selects all checkboxes in the header
	*/
	this.selectAllCheckboxes = function()
	{
		for(var i in this.checkboxes)		
			this.checkboxes[i].el.checked = true;		
	}
	
	/*
	*	@method View.clearAllCheckboxes
	*	unselects all checkboxes in the header
	*/
	this.clearAllCheckboxes = function()
	{
		for(var i in this.checkboxes)		
			this.checkboxes[i].el.checked = false;		
	}
	
	/*
	*	@method: View.zoomToTown
	*	center the map on the selected town and zoom in
	*/
	this.zoomToTown = function(coordinates)
	{			
		if(coordinates.lat == 0 || coordinates.lng == 0) return;
		
		var x_min = coordinates.LONG_MIN_X;
		var x_max = coordinates.LONG_MAX_X;
		var y_min = coordinates.LAT_MIN_Y;
		var y_max = coordinates.LAT_MAX_Y;
					
		var polyPoints = Array();

		var point1 = new GLatLng(y_min, x_min);
		var point2 = new GLatLng(y_max, x_min);
		var point3 = new GLatLng(y_max, x_max);
		var point4 = new GLatLng(y_min, x_max);		

	    polyPoints.push(point1);
		polyPoints.push(point2);
		polyPoints.push(point3);
		polyPoints.push(point4);
		
		var polygon = new GPolygon(polyPoints);
		// or for visible polygon...
		//var polygon = new GPolygon(polyPoints,"#000000",2,.5,"#ff0000",.5);
		this.map.addOverlay(polygon);
		var zoomIndex = this.map.getBoundsZoomLevel(polygon.getBounds());		
		this.map.setCenter(new GLatLng(coordinates.lat, coordinates.lng), zoomIndex);		
		
		var viewBounds;
		var zoom = this.map.getZoom();
		var markers = this.markerGroups.ALL;
		var matchFound = false;
		
		while(zoom > this.CONSTANTS.ZOOM_INDEX)
		{
			viewBounds = this.map.getBounds();
			for(var i in markers)
			{
				if(!markers[i].isHidden()) 
				{						
					matchFound = true;
					if(viewBounds.containsLatLng(markers[i].getLatLng())) return;
				}				
			}	  
			if(!matchFound) 
			{
				this.map.setZoom(this.CONSTANTS.TOWN_LEVEL_ZOOM_INDEX);
				return;
			}
			zoom--;
			this.map.setZoom(zoom);
		}			
	}
		
	/*
	*	@method: View.getSelectedTown
	*	return the town name selected in the UI
	*/
	this.getSelectedTown = function()
	{
		return this.selects[0].el.options[this.selects[0].el.selectedIndex].text;		
	}
	
	/*
	*	@method: View.loadSelects
	*	loads data into UI select elements												
	*/
	this.loadSelects = function(datatype, data)	
	{
		switch(datatype)
		{
			case 0:
				var el = document.createElement('option');
				el.innerHTML = "";
				this.selects[0].el.appendChild(el);
				for(var i in data)					
				{	
					var el = document.createElement('option');
					el.innerHTML = data[i].name;
					this.selects[0].el.appendChild(el);
				}					
				break;
		}	
	}
	
	/*
	*	@method: View.recenterMap
	*	recenter the map to initial coordinates
	*/
	this.recenterMap = function(point)
	{					
	    this.map.setCenter(new GLatLng(point.lat(), point.lng()));			
	}
	
	/*
	*	@method View.setSelectWidth
	*	sets the width of a select element
	*/
	this.setSelectWidth = function(width)
	{
		for(var i in this.selects)
		{
			switch(this.selects[i].name)
			{
				case "sel_towns":
					this.selects[i].el.style.width = width + "em";
					break;
			}
		}
	}
		
}//end class View
