/**
 * $Id: googleMap.js,v 1.27 2010/03/29 01:41:11 cvs Exp $
 *
 * @author Frederick J Richart
 * @copyright Copyright © 2006-2009, Useful Media Planet, LLC, All rights reserved.
 */
 /**
  * GoogleMapMarker implements an instance of a Fred's Used websites special
  * marker.  The marker has the traditional pin point marker showing an info-window
  * with the address information but it also is paired with an options street guy
  * that is pre-positioned to show the visitor a street view you wish them to start
  * with.
  */
 function GoogleMapMarker(index, lat, lng, text, draggable, streetData, hidden, doStreetLink) {
 	this.index = index;
 	this.lat = lat;
 	this.lng = lng;
 	this.text = text;
 	this.draggable = draggable ? true : false;
 	this.hidden = hidden ? true : false;
 	this.doStreetLink = doStreetLink
 	if (streetData) streetData.doStreetLink = doStreetLink;
 	this.streetData = streetData;
 	if (!Utilities.GoogleMapMarkers) Utilities.GoogleMapMarkers = new Object();
 	Utilities.GoogleMapMarkers[index] = this;
 }
 GoogleMapMarker.prototype = {
 	onPageLoad : function() {
 		var t = this, marker;
 	},
 	setPoint : function(point) {
 		this.marker.setPoint(point);
 	},
 	addToMap : function(map) {
 		var t = this, marker;
 		t.map = map;
 		t.idPrefix = map.idPrefix;
 	 	t.point = new GLatLng(t.lat, t.lng);
		marker = t.marker = new GMarker(t.point, {draggable:true});
		t.enableMarker(!t.hidden);
		map.gmap.addOverlay(marker); 
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(t.text);
		});
		t.makeDraggable(t.draggable);
		if (t.streetData) t.streetView = new GoogleStreetView(t, t.streetData);
 	},
 	makeDraggable : function(dragable) {
 		var t = this, marker = t.marker;
 		if (t.draggable = dragable) {
 			marker.enableDragging();
			GEvent.addListener(marker, "dragstart", function() {
				marker.closeInfoWindow();
			});
			GEvent.addListener(marker, "dragend", function() {
				var p = marker.getPoint(), idp = t.idPrefix;
				marker.openInfoWindowHtml(t.text);				
				$(idp + 'latitude').val(p.lat());
				$(idp + 'longitude').val(p.lng());
			}); 
 		} else {
 			marker.disableDragging();
 		}		
 	},
 	enableMarker : function(show) {
 		var t = this, m = t.marker;
 		show ? m.show() : m.hide();
 		if (t.streetView) t.streetView.enableMarker(show);
 	},
 	openInfoWindowHtml : function(text) {
 		this.marker.openInfoWindowHtml(text ? text : this.text);
 	},
 	getLatLng : function() {
 		return this.marker.getLatLng();
 	},
 	showStreet : function() {
 		var t = this, sv = t.streetView;
 		if (sv) {
 			sv.enableMarker(true);
 			sv.openPanorama(true);
 		}
 	}
}
/**
 * GoogleStreetView implements the street view markers that are paired with regular
 * markers showing a pre-configured street view of a given location.
 */
function GoogleStreetView(marker, params) {
	if (!params.edit && !params.enabled) return null;
	var t = this, stmarker, guyIcon = new GIcon(G_DEFAULT_ICON), point, map = marker.map, x, idp;
	point = new GLatLng(params.latitude, params.longitude);
	t.params = params;
	t.gmarker = marker;
	t.map = map;
	t.client = new GStreetviewClient();
	idp = t.idPrefix = map.idPrefix ? map.idPrefix : '#';
	guyIcon.image = "http://maps.gstatic.com/intl/en_us/mapfiles/cb/man_arrow-0.png";
	guyIcon.transparent = "http://maps.gstatic.com/intl/en_us/mapfiles/cb/man-pick.png";
	guyIcon.imageMap = [
		26,13, 30,14, 32,28, 27,28, 28,36, 18,35, 18,27, 16,26,
		16,20, 16,14, 19,13, 22,8
 	];
	guyIcon.iconSize = new GSize(49, 52);
	guyIcon.iconAnchor = new GPoint(25, 35);  // near base of guy's feet
	guyIcon.infoWindowAnchor = new GPoint(25, 5);  // top of guy's head
	
	if (params.edit) {
		t.longitude_ctl = $(idp + 'str_longitude').get(0);
		t.latitude_ctl = $(idp + 'str_latitude').get(0);
		t.yaw_ctl = $(idp + 'str_yaw').get(0);
		t.pitch_ctl = $(idp + 'str_pitch').get(0);
		t.zoom_ctl = $(idp + 'str_zoom').get(0);
	}

	stmarker = t.marker = new GMarker(point, {icon: guyIcon, draggable: true, hide: params.enabled ? false : true});
	map.gmap.addOverlay(t.marker);
	t.enableMarker(!params.doStreetLink);
	t.lastMarkerLocation = point;
	GEvent.addListener(stmarker, "dragend", function() {
		t.onDragEnd();
	});
	GEvent.addListener(stmarker, "click", function(){
		t.openPanorama(false);
	});
	t.onYawChange(params.yaw);
}
GoogleStreetView.prototype = {
	openPanorama : function(hideMarkerOnClose) {
		var t = this, panorama = t.panorama;
		if (!panorama) t.createPanorama();
		if (!t.infoWindow) {
			t.infoWindow = true;
			t.marker.openInfoWindow(t.smallNode, {maxContent: t.contentNode, maxTitle: "Full screen"});
		}
		t.panorama.show();
		t.panorama.checkResize();
		t.hideMarkerOnClose = hideMarkerOnClose;
	},
	createPanorama : function() {
		var t = this, params = t.params, stmarker = t.marker, panorama, gmap = t.map.gmap, iw = gmap.getInfoWindow(), contentNode, smallNode;
		t.contentNode = contentNode = document.createElement('div');
		contentNode.style.textAlign = 'center';
		contentNode.style.width = '550px';
		contentNode.style.height = '350px';
		contentNode.innerHTML = 'Loading panorama';
	
		t.smallNode = smallNode = document.createElement('div');
		smallNode.style.width = '300px';
		smallNode.style.height = '300px';
		smallNode.id = 'pano';
	
		panorama = t.panorama = new GStreetviewPanorama(smallNode);
		panorama.setLocationAndPOV(stmarker.getLatLng(), params);
		GEvent.addListener(panorama, "newpano", function(lat, lng) {
			t.onNewLocation(lat, lng)
		});
		GEvent.addListener(panorama, "yawchanged", function(yaw) {
			t.onYawChange(yaw)
		});
		GEvent.addListener(panorama, "pitchchanged", function(pitch) {
			t.onPitchChange(pitch);
		});
		GEvent.addListener(panorama, "zoomchanged", function(zoom) {
			t.onZoomChange(zoom);
		});
		GEvent.addListener(panorama, "initialized", function(location){
			t.onLocationInitialized(location);
		});
		GEvent.addListener(panorama, "error", function(errorCode){
			var e = errorCode;
		});
		GEvent.addListener(iw, "maximizeend", function() {
			panorama.setContainer(contentNode); 
			window.setTimeout(function(){
				panorama.checkResize();
			}, 5);
		});		
		GEvent.addListener(stmarker, "infowindowbeforeclose", function() {
			panorama.hide();
			if (t.hideMarkerOnClose) stmarker.hide();
		});
	},
	enableMarker : function(show) {
		var t = this;
		if (t.marker) {
			return (show) ? t.marker.show() : t.marker.hide(); 
		}
	},
	onYawChange : function(newYaw) {
		var t = this, params = t.params;
		//var GUY_NUM_ICONS = 16;
		//var GUY_ANGULAR_RES = 360/16;
		if (newYaw < 0) {
			newYaw += 360;
		}
		t.guyImageNum = Math.round(newYaw/22.5) % 16;
		t.guyImageUrl = "http://maps.gstatic.com/intl/en_us/mapfiles/cb/man_arrow-" + t.guyImageNum + ".png";
		t.marker.setImage(t.guyImageUrl);
		params.yaw = newYaw;
		if (params.edit && t.yaw_ctl) t.yaw_ctl.value = newYaw;
	},
	onPitchChange : function(spitch) {
		var t = this, params = t.params;
		params.pitch = pitch;
		if (params.edit && t.pitch_ctl) t.pitch_ctl.value = pitch;
	},
	onZoomChange : function(zoom) {
		var t = this, params = t.params;
		params.zoom = zoom;
		if (params.edit && t.zoom_ctl) t.zoom_ctl.value = zoom;
	},
	onNewLocation : function(lat, lng) {
		var t = this, params = t.params;
		var latlng = new GLatLng(lat, lng);
		t.marker.setLatLng(latlng);
	},
	onDragEnd : function() {
		var t = this, params = t.params, latlng = t.marker.getLatLng();
		if (!t.panorama) t.createPanorama();
		t.client.getNearestPanorama(latlng, function(response) {
			t.onResponse(response);
		});
	},
	onResponse : function(response) {
		var t = this, marker = t.marker, panorama = t.panorama;
		if (response.code != 200) {
			marker.setLatLng(t.lastMarkerLocation);
		} else {
			t.setNewLocation(response.Location.lat, response.Location.lng);
		}
	},
	setNewLocation : function(lat, lng) {
		var t = this, marker = t.marker, panorama = t.panorama, latlng;
		var latlng = new GLatLng(lat, lng);
		marker.setLatLng(latlng);
		t.lastMarkerLocation = latlng;
		if (panorama) {
			panorama.setLocationAndPOV(latlng, panorama.getPOV());
			panorama.checkResize();
		}
		if (t.params.edit && t.latitude_ctl) t.latitude_ctl.value = lat;		
		if (t.params.edit && t.longitude_ctl) t.longitude_ctl.value = lng;
	},
	onLocationInitialized : function(location) {
		var t = this, params = t.params;
		t.marker.setLatLng(location.latlng);
	}
}
/**
 * GoogleRoute implements the javascript part of get directions.  Creating
 * an instance of this object provides a mechanism for controlling the get
 * directions functionality for a given map.
 */
function GoogleRoute(map, inputID, routeID, locale) {
	var t = this;
	t.map = map;
	t.locale = locale;
	t.panel = document.getElementById(routeID);
	t.input = document.getElementById(inputID);
	t.directions = new GDirections(map.gmap, t.panel);
	t.isOpen = false;
	map.route = t;
}
GoogleRoute.prototype = {
	open : function() {
		var t = this, e = t.map.element;
		if (t.isOpen) return;
		$(e).animate({width:'70%'}, {queue:false, duration:1000})
		$(t.panel).animate({width:'25%'},{queue:false, duration:1000, complete:function(){
			$(t.panel).css({visibility:"visible",overflow:''});
		}});
		t.map.gmap.checkResize();		
	},
	getRoute : function(marker) {
		var t = this;
		t.open();
		t.directions.loadFromWaypoints([t.input.value, marker.getLatLng()],{locale:t.locale});
	},
	setHeight : function(height) {
		$(this.panel).css({height:height});
	}
}
/**
 * This implements a google map.  The map is an instance of possibly several
 * map areas on a given web page all acting independently of each other.  The
 * map must be associated with a container in which to build the map.
 */
function GoogleMap(id, lat, lng, color, zoom, showStreet, selectIndex, centerIndex, showLabels, idPrefix, markers) {
	this.id = '#' + id;
	this.idPrefix = '#' + (idPrefix ? idPrefix : '');
	this.lat = lat;
	this.lng = lng;
	this.color = color;
	this.zoom = zoom;
	this.showStreet = showStreet;
	this.selectIndex = selectIndex;
	this.centerIndex = centerIndex;
	this.showLabels = showLabels;
	this.markers = markers;
	this.overlayInstance = null;
 	Utilities.onload(this);
 	if (!Utilities.GoogleMaps) Utilities.GoogleMaps = new Array();
 	Utilities.GoogleMaps[id] = this;
}
GoogleMap.prototype = {
	onPageLoad : function() {
		var t = this, e, gmap, v, m,i;
		if (!(e = $(t.id))) return;
		t.element = e;
		e.GoogleMap = t;
		if (!GBrowserIsCompatible()) {
			e.GoogleMap = false;
			return;
		}
	    v = {
	    	backgroundColor: t.color,
	    	googleBarOptions: {
	    		showOnLoad : true,
	    		style : "new"
	    	}
	    };
	    t.gmap = gmap = new GMap2($(e).get(0), v);
		$(e).css({'background-color': t.color});
		gmap.addMapType(G_PHYSICAL_MAP);
		gmap.enableContinuousZoom();
		gmap.enableGoogleBar();
		gmap.enableScrollWheelZoom();
		gmap.addControl(new GLargeMapControl());
		gmap.addControl(new GMapTypeControl());
		t.setCenter(t.lat, t.lng, t.zoom); 
		t.markers = jQuery.extend(true, {}, Utilities.GoogleMapMarkers, t.markers);
		for (i in t.markers){
			t.markers[i].addToMap(t);
		}
		if (t.showStreet) {
			if (t.zoom > 14) t.toggleOverlay();
			GEvent.addListener(gmap, "zoomend", function(oldLevel, newLevel){
				if ((newLevel < 14 && t.overlayInstance) ||(newLevel > 14 && !t.overlayInstance)) {
					t.toggleOverlay();
				}
			});
		}
		if (t.selectIndex) t.selectMarker(t.selectIndex, t.showLabels);
		if (t.centerIndex) t.panToMarker(t.centerIndex);
	},
	toggleOverlay : function() {
		var t = this, gmap = t.gmap, params = t.params;
		if (!t.overlayInstance) {
			t.overlayInstance = new GStreetviewOverlay();
			gmap.addOverlay(t.overlayInstance);
		} else {
			gmap.removeOverlay(t.overlayInstance);
			t.overlayInstance = null;
		}
	},
	setCenter : function(lat, lng, zoom) {
		this.gmap.setCenter(new GLatLng(lat,lng), zoom);
	},
	selectMarker : function(index, showLabels) {
		var t = this, m;
		if (!(m = t.markers[index])) return;
		t.selectedMarker = m = t.markers[index];
	 	if (showLabels) m.openInfoWindowHtml(); 		
	},
	selectMarkerPan : function(index, showLabels, defMarker) {
		var t = this, m;
		if (!(m = t.markers[index]) && !(m = t.markers[defMarker])) return null;
		t.selectedMarker = m;
		t.gmap.panTo(m.point);	
 		if (showLabels) m.openInfoWindowHtml();
 		return m;		
	},
	panToMarker : function(index) {
		var t = this, m;
		if (!(m = t.markers[index])) return;
		m = t.markers[index];
		t.gmap.panTo(m.point);	
	},
	showAddress : function(index) {
		// Retrieve address from form
		var geocoder, t = this, idp = t.idPrefix,
			street1 = $(idp + 'street1').get(0).value,
			street2 = $(idp + 'street2').get(0).value,
			city = $(idp + 'city').get(0).value,
			state = $(idp + 'state').get(0).value,
			zip = $(idp + 'zip').get(0).value,
			address = street1;
		if (street2) address += ", " + street2;
		if (city) address += ", " + city;
		if (state) address += ", " + state;
		if (zip) address += "  " + zip;
		if (!(geocoder = Utilities.GoogleGeocoder)) {
			geocoder = Utilities.GoogleGeocoder = new GClientGeocoder();
		}
		if (!index) index = 1;
	  	geocoder.getLatLng(address, function(point) {
			if (!point) {
				alert(address + " not found");
			} else {
				var m;
				if (!t.gmap) return;
				if (!(m = t.markers[index])) {
					m = t.markers[index] = new GoogleMapMarker(index, point.lat, point.lng, "address", t.draggable, {longitude:point.lng,latitude:point.lat,enabled:true});
				}
				m.setPoint(point);
				t.gmap.panTo(point);	
				m.openInfoWindowHtml(address);
				$(idp + 'latitude').val(point.lat());
				$(idp + 'longitude').val(point.lng());
				if (m.streetView) m.streetView.setNewLocation(point.lat(), point.lng());
			}
		});
	},
	checkStreetEnable : function(e) {
		var t = this, m = t.selectedMarker;
		m.streetView.enableMarker(e.checked);
	},
	getDirections : function(inputID, routeID, locale) {
		var t = this, marker;
		if (!t.route) {
			t.route = new GoogleRoute(t, inputID, routeID, locale);
		}
		t.route.getRoute(t.selectedMarker);
	},
	checkResize : function(event, ui) {
		var t = this, gmap = t.gmap, h, pos, e = t.element, p = $(e).parent(), g = $(p).parent(), r = t.route;
		if (!gmap) return;
		pos = $(p).position();
		h = $(g).height() - pos.top;
		$(p).css({height:h});
		$(e).css({height:h});
		if (r) r.setHeight(h);
		gmap.checkResize();
	},
	expandEditPopup : function(e, popupID, selectorID, locationID, defLocIndex) {
		var t = this, selector, marker;
		t.defLocIndex = defLocIndex;
		GeneralEvent.Config(e, popupID, {CallbackObject:t});
		GeneralEvent.Expand(e, popupID);
		if (selectorID) {
			t.editMarkerSelector = selector = $('#'+selectorID);
			locationID = $(selector).get(0).value;
		} else if (locationID) {
			t.editMarkerSelector = null;
		} else {
			alert("Application Error: no selector nor location specified");
			return false;
		}
		t.editEnableMarker(locationID, defLocIndex);
		t.loadForm(locationID);
	},
	editEnableMarker : function (locationID, defLocIndex) {
		var t = this, marker = t.selectMarkerPan(locationID, true, defLocIndex);
		marker.makeDraggable(true);
		marker.enableMarker(true);
		t.checkResize();		
	},
	ServerResponse : function(popup, xdomAjax, response) {
		var t = this, id, reference, opt, index, sel = t.editMarkerSelector, sele = sel.get(0),e, idp = t.idPrefix, m = t.selectedMarker;
		if (!popup.ok) return;
		e = xdom_GetFirstElementWithTagName(response, 'new_id');
		if (!e) return;
		id = e.getAttribute("value");
		reference = xdom_GetData(e);
		
		// Should the server send back an existing marker ID we should find that
		sel.children('option').each(function(i){
			if (this.value == id) {
				opt = this;
				index = this.index;
				return false;
			}
		});
		if (!opt) {
			// OK, new marker
			sel.append('<option value="' + id + '">' + reference + '</option>');
			index = sele.options.length -1;
		}
		sele.selectedIndex = index;
		$(idp + 'rec_id').val(id);
		// Create a new marker to replace the default marker we just used
		if (t.defLocIndex == m.index) {
			e = new GoogleMapMarker(m.index, m.latitude, m.longitude, 'New Marker', true, {edit:true,latitude:m.latitude, longitude:m.longitude});
			t.markers[id] = m;
			e.addToMap(t);
		}
	},
	loadForm : function(locationID) {
		var t = this, d, sv, idp = t.idPrefix, v;
		if (!(d = GoogleMapMarkerData[locationID])) {
			d = {rec_id:"",status:"1",page:"",title:"",reference:"",name:"",url:"",street1:"",street2:"",city:"",state:"",zip:"",image:"",latitude:"40.451600788468554",longitude:"-105.06407976150513",sort_order:"1",streetView:{longitude:"-105.06407976150513",latitude:"40.451600788468554",yaw:"",pitch:"",zoom:"0",edit:true,enabled:true}};
		}
		$(idp + 'rec_id').val(locationID);
		$(idp + 'sort_order').val((v=d.sort_order) ? v : '');
		$(idp + 'latitude').val((v=d.latitude) ? v : '');
		$(idp + 'longitude').val((v=d.longitude) ? v : '');
		$(idp + 'reference').val((v=d.reference) ? v : '');
		$(idp + 'title').val((v=d.title) ? v : '');
		$(idp + 'name').val((v=d.name) ? v : '');
		$(idp + 'url').val((v=d.url) ? v : '');
		$(idp + 'street1').val((v=d.street1) ? v : '');
		$(idp + 'street2').val((v=d.street2) ? v : '');
		$(idp + 'city').val((v=d.city) ? v : '');
		$(idp + 'state').val((v=d.state) ? v : '');
		$(idp + 'zip').val((v=d.zip) ? v : '');
		$(idp + 'image').val((v=d.image) ? v : '');
		$(idp + 'enabled').get(0).checked = ((d.status & 1) == 1);
		$(idp + 'secondary').get(0).checked = ((d.status & 2) == 2);
		
		// Street Data
		sv = d.streetView;
		$(idp + 'str_latitude').val((v=sv.latitude) ? v : '');
		$(idp + 'str_longitude').val((v=sv.longitude) ? v : '');
		$(idp + 'str_yaw').val((v=sv.yaw) ? v : '');
		$(idp + 'str_pitch').val((v=sv.pitch) ? v : '');
		$(idp + 'str_zoom').val((v=sv.zoom) ? v : '');
		$(idp + 'str_enabled').get(0).checked = (sv.enabled);
	}
}
function GooglePopupContainer(map, popupID, width, height, title) {
	var t = this;
	t.map = map;
	t.popupID = popupID;
	t.width = width;
	t.height = height;
	t.title = title;
	$(document).ready(function(){
		t.ready();
	});
}
GooglePopupContainer.prototype = {
	ready : function() {
		var t = this, pid = '#' + t.popupID, map = t.map, w = t.width, h = t.height;
		var check = function(event,ui){
			map.checkResize(event,ui);
		}
		t.popup = $(pid).dialog({
			autoOpen:false,
			width:w,
			height:h,
			show:'slide',
			title:t.title,
			dialogClass:'GoogleMapPopupWidget',
			resizeStop:check,
			open:check,
			zIndex:20025
		});
		$(pid).css({display:''});
	},
	open : function(e) {
		this.popup.dialog("open");
	}
}