/**
HubOnline Map Search
version 1.0

namespace: jQuery.hubDetailMap

functions:
 - init
 - pageData
 - populate
 - createMarker
 - focusListing
 - getData
 
private members:
 - Tooltip
 - HTMLControl
 
*/

;(function($){

	// Initialise hubDetailMap Object
	$.hubDetailMap = {};
	
	/**
		errorMessages:
		 - the global object for standard error messages
	*/
	$.hubDetailMap.errorMessages = {
		en : {
			functionDoesNotExist : "hubDetailMap Error 1: The function does not exist",
			addressNotFound: "This address cannot be found.  Please modify your search.",
			browserNotCompatible: "This browser is reported as being not compatible with Google Maps.",
			cannotLoad: "Cannot load the Google Maps API at this time.  Please check your connection.",
			invalidLatLng: "Invalid Latitude and Longitude entered for Google Map"
		}
	};
	
	/**
	defaultOptions:
	 - override by passing an anon object to the map constructor
	*/
	$.hubDetailMap.defaultOptions = {
		// Initial type of map to display
		language: "en",
		// mapType options: "map", "sat", "hybrid"
		mapType: "map",
		// default map center is Australia
		mapCenter: [-25.274395,133.775136],
		mapDimensions: [600, 600],
		mapZoom: 3,
		toggleButton: 'toggleMap',
		// mapControlSize options: "large", "small"	
		mapControlSize: "large",		

		// GMap settings
		mapEnableType: true,
		mapEnableOverview: false,
		mapEnableDragging: true,
		mapEnableInfoWindows: true,
		mapEnableDoubleClickZoom: false,
		mapEnableScrollZoom: false,
		mapEnableSmoothZoom: false,
		mapEnableGoogleBar: false,
		mapEnableScaleControl: false,
		mapShowjMapIcon: true,

		// Map Search settings
		mapShowPaginationControl: true,
		mapShowResultControl: true,
		agentID: 2045,
		iconImagePath: '/img/gmaps/markers/',
		agentsFolderPath: 'http://media.hubonline.com.au/agents_folder/',
		resultsPerPage: 50,
		xslID: 2045,

		// Street View Defaults
		streetViewContainer: 'streetView',
		streetViewSuccess: true
	};
	
	$.hubDetailMap.init = function(el, options, callback) {
		var options = $.extend({}, $.hubDetailMap.defaultOptions, options);
		var options = this.options = $.meta ? $.extend({}, options, $(this).data()) : options;
		
		// We do this to reduce overhead from making multiple $(el) calls
		var GMSelector = $(el);
		
		this.mapElement = el;
		this.listings = options.listings[0];
					
		// TODO
		// check for any other instances of the map and bail, or at least until there's sufficient encapsulation
		
		// Check for valid Google Map lat/lng values
		// IF values aren't numbers (eg. string) return FALSE
		// IF values are === to int 0 (the number zero) return FALSE
		var validGoogleMap = $.hubDetailMap.isNumber([this.listings.latitude,
																								this.listings.longitude,
																								this.listings.mapCenterLat,
																								this.listings.mapCenterLng,
																								this.listings.streetview.latitude,
																								this.listings.streetview.longitude,
																								this.listings.streetview.pov.yaw,
																								this.listings.streetview.pov.pitch,
																								this.listings.streetview.pov.zoom]);
		
		if(!validGoogleMap) {
			GMSelector.text(this.errorMessages[options.language].invalidLatLng).css({
				color: "#f00"
			});
			throw Error(this.errorMessages[options.language].invalidLatLng);
		}
		
		// Check for GMap compatibility  
		
		if (typeof google.maps.BrowserIsCompatible == 'undefined') {
			GMSelector.text(this.errorMessages[options.language].cannotLoad).css({
				color: "#f00"
			});
			throw Error(this.errorMessages[options.language].cannotLoad);
		}
			
		if (!GBrowserIsCompatible()) {
			GMSelector.text(this.errorMessages[options.language].browserNotCompatible).css({color: "#f00"});
			throw Error(this.errorMessages[options.language].browserNotCompatible);
		}
		
		// Create our Google Map Object
		$.hubDetailMap.addGoogleMap(el);

		
		// Add Map Marker (if required)
		if(parseInt(this.listings.showMarker) === 1) {
			$.hubDetailMap.marker = new MarkerManager($.hubDetailMap.GMap2);
			$.hubDetailMap.attachMarker();
		}
		
		// Create our Street View Object
		if(parseInt(this.listings.streetview.showStreetview) === 1) {
			$.hubDetailMap.createStreetView(this.listings.streetview);
		} else {
			$('#' + this.options.toggleButton + '').css('display','none');
		}
		
		if (typeof callback == 'function') return callback(el, options);
	}
	
	$.hubDetailMap.attachMarker = function() {
		var lat = this.listings.latitude;
		var lng = this.listings.longitude;
		this.marker.addMarker(new google.maps.Marker(new google.maps.LatLng(lat, lng),{clickable: false}),0);
	}
	
	$.hubDetailMap.createStreetView = function(streetView) {
		// Store the streetView container for easy access
		var container = this.options.streetViewContainer;
		
		// Get our Width / Height to match our Google Map
		var width = this.options.mapDimensions[0];
		var height = this.options.mapDimensions[1];
		
		// Create DIV for Street View
		$('<div id="' + container + '"></div>')
			.insertAfter(this.mapElement)
			.width(width)
			.height(height)
			.css('display','none');
		
		// Create our Street View Object
		var svClient = this.svClient = new google.maps.StreetviewClient();
		var svObject = this.svClient = new google.maps.StreetviewPanorama($('#' + container).get(0));
		
		// Set Lat/Lng + Options
		if(streetView.latitude && streetView.longitude) {
			var svLatlng = new google.maps.LatLng(streetView.latitude,streetView.longitude);
			var svOptions = {yaw:streetView.pov.yaw,pitch:streetView.pov.pitch,zoom:streetView.pov.zoom};
			// Set Location + POV
			svObject.setLocationAndPOV(svLatlng, svOptions);
			// Add a button to toggle between Google Maps and Street View
			$.hubDetailMap.addToggle();
		} else {
			$.hubDetailMap.findStreetNode(svObject,svClient);
		}
		
		
	}
	
	$.hubDetailMap.findStreetNode = function(svObject,svClient) {
		var currentMarker = new google.maps.Marker(new google.maps.LatLng(this.listings.latitude,this.listings.longitude));
		var functionVar = function(panoramaData) {
      if (panoramaData.code != 200) {
				$.hubDetailMap.streetViewSuccess = false;
				return
			} else {
				var angle = $.hubDetailMap.computeAngle(currentMarker.getLatLng(),panoramaData.location.latlng);
				svObject.setLocationAndPOV(panoramaData.location.latlng, {yaw: angle});
				// Add a button to toggle between Google Maps and Street View
				$.hubDetailMap.addToggle();
			}
		}
		svClient.getNearestPanorama(currentMarker.getLatLng(),functionVar);
	}
	
	$.hubDetailMap.computeAngle = function(endLatLng, startLatLng) {
      var DEGREE_PER_RADIAN = 57.2957795;
      var RADIAN_PER_DEGREE = 0.017453;

      var dlat = endLatLng.lat() - startLatLng.lat();
      var dlng = endLatLng.lng() - startLatLng.lng();
      // We multiply dlng with cos(endLat), since the two points are very closeby,
      // so we assume their cos values are approximately equal.
      var yaw = Math.atan2(dlng * Math.cos(endLatLng.lat() * RADIAN_PER_DEGREE), dlat)
             * DEGREE_PER_RADIAN;
      return $.hubDetailMap.wrapAngle(yaw);
   }
	 
	$.hubDetailMap.wrapAngle = function(angle) {
    if (angle >= 360) {
      angle -= 360;
    } else if (angle < 0) {
     angle += 360;
    }
    return angle;
  };
	
	$.hubDetailMap.addToggle = function() {
		var container = this.options.streetViewContainer;
		$('#' + this.options.toggleButton + '')
			.append('<a href="javascript:void(0)">Street View</a>')
			.click(function(){
				// Get our containers
				var svContainer = $('#' + container);
				var mapContainer = $('#' + $.hubDetailMap.mapElement.id);
				$('#' + this.id + ' a').toggleClass('backToGoogleMap');
				// Toggle our containers
				mapContainer.toggle();
				svContainer.toggle();
				//Swap our Link text
				if($('#' + container + ':visible').size()) {
					$('#' + this.id + ' a').html('Google Map');
				} else {
					$('#' + this.id + ' a').html('Street View');
				}
			})
	}
	
	$.hubDetailMap.isNumber = function(numbers) {
		for(var i = 0; i < numbers.length; i++) {
			if(isNaN(numbers[i]) && numbers[i] !== 0) {
				return false;
			}
		}
		return true;
	}
	
	$.hubDetailMap.addGoogleMap = function(el) {
		// Set DIV dimensions
		$(el).width(this.options.mapDimensions[0]).height(this.options.mapDimensions[1]);
		
		// initialise the GMap2 object
			
		el.hubDetailMap = this.GMap2 = new google.maps.Map2(el);
			
		// cleanup crew to window.unload please
		
		$(window).unload(function(){
				google.maps.Unload();
		});
		
		switch(this.options.mapType) {
			case "map":
				var mapType = G_NORMAL_MAP;
				break;
			case "sat":
				var mapType = G_SATELLITE_MAP;
				break;
			case "hybrid":
				var mapType = G_HYBRID_MAP;
				break;
		}
		
		el.hubDetailMap.setCenter(
			new google.maps.LatLng(this.listings.mapCenterLat, this.listings.mapCenterLng), 
			this.listings.mapZoom, 
			mapType
		);
		
		// Set map options
		var mapControls = el.hubDetailMap.getDefaultUI();
				mapControls.zoom.scrollwheel = false;
		
		switch (this.options.mapControlSize) {
			case "small":
				mapControls.controls.smallzoomcontrol3d = true;
				mapControls.controls.largemapcontrol3d = false;
				mapControls.controls.scalecontrol = false;
				break;
			case "large":
				mapControls.controls.smallzoomcontrol3d = false;
				mapControls.controls.largemapcontrol3d = true;
				break;
		}
		el.hubDetailMap.setUI(mapControls);
	
		if (this.options.mapEnableType) {
			el.hubDetailMap.addControl(new google.maps.MapTypeControl()); 
		}
			
		if (this.options.mapEnableOverview) {
			el.hubDetailMap.addControl(new google.maps.OverviewMapControl());
		}
		
		if (!this.options.mapEnableDragging) {
			el.hubDetailMap.disableDragging(); 
		}
		
		if (!this.options.mapEnableInfoWindows) {
			el.hubDetailMap.disableInfoWindow(); 
		}
		
		if (this.options.mapEnableDoubleClickZoom) {
			el.hubDetailMap.enableDoubleClickZoom(); 
		}
		
		if (this.options.mapEnableScrollZoom) {
			el.hubDetailMap.enableScrollWheelZoom();
		}
		
		if (this.options.mapEnableSmoothZoom) {
			el.hubDetailMap.enableContinuousZoom();
		}
		
		if (this.options.mapEnableGoogleBar) {
			el.hubDetailMap.enableGoogleBar();
		}
		
		if (this.options.mapEnableScaleControl) {
			el.hubDetailMap.addControl(new google.maps.ScaleControl());
		}
	}
	
	/**
	jQuery(expr).hubDetailMap(options)
	 - bind the sucker to the jQuery object and off we go
	*/
	$.fn.hubDetailMap = function(options, callback) {
		return this.each(function(){
			$.hubDetailMap.init(this, options, callback);
		});
	}
})(jQuery);
