




/*jslint eqeqeq: true, undef: true */
/*global $, jQuery, BTT, window, document, swfobject, confirm, prompt, VEMap,
  VELatLong, VEMapStyle, VEMapOptions, VEMap, VELatLong, VEShapeType, VEShape,
  VEShapeLayer, VEMapViewSpecification, VEClusteringType, VEMapMode*/


/**
 * BT Tradespace Virtual Earth module
 * @namespace BT Tradespace Virtual Earth module
 * @requires Virtual Earth map control 6.2 - http://www.microsoft.com/maps/developers/
 * @member BTT
 */
BTT.Utilities = window.BTT.Utilities || {};
BTT.Utilities.ensureBingJS = function( func ) {
	
	var bingJSUrl = 'http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2',
		bingCompatabilityJSUrl = 'http://dev.virtualearth.net/mapcontrol/v6.2/js/atlascompat.js';
		
	if (typeof VEMap === "undefined" && $('[class*=JS_map]').length > 0) {

		// Function to load the Bing maps script file dynamically when needed
		var fetchMapJS = function(){
			$.getScript( bingJSUrl, function(){
				if(typeof func === "function") {
					func();
				}
			});
		};
		// Firefox requires a 'compatability' script, see below:
		// http://code.davidjanes.com/blog/2008/11/08/how-to-dynamically-load-map-apis/
		// http://soulsolutions.com.au/Blog/tabid/73/EntryId/519/Load-Virtual-Earth-on-Demand.aspx
		if (!(window.attachEvent)) {
			$.getScript( bingCompatabilityJSUrl, fetchMapJS );
		} else {
			fetchMapJS();
		}
	} else {
		if(typeof func === "function") {
			func();
		}
	}
};


BTT.Maps = {
	
	allMaps: {
		clickMaps: [],
		maps: []
	},
	
	// Object class
	Map: (function(){
		
		// Contructor for instances
		var mapConstructor = function(newId){

			// Private attributes
			var id,
				myParams = {
					VELatLong: new VELatLong(51.5080823,-0.1282095),
					zoom: 16,
					style: VEMapStyle.Road,
					fixed: false,
					mode: VEMapMode.Mode2D,
					showSwitch: false,
					tileBuffer: 1,
					mapOptions: (function(){
						var options = new VEMapOptions();
							options.EnableBirdseye = false;
							options.EnableDashboardLabels = false;
						return options;
					}()),
					clickMapClass: "JS_clickMap",
					mapClass: "JS_map",
					vcards: []  // An array of vcards on the page, gets set by JS
				},
				isMultipointMap = false;
			
			// Public, privaleged functions	
			this.getID = function() {
				return id;
			};
			this.setID = function( newId ) {
				id = newId;
			};
			this.getParam = function( paramName ){
				return myParams[ paramName ];
			};
			this.setParam = function( paramName, newValue ){
				if (typeof myParams[paramName] !== "undefined") {
					myParams[paramName] = newValue;
				} else {
					throw new Error("no such parameter exists");
				}
			};
			this.isMultiPointMap = function(){
				return isMultipointMap;
			};
			this.setMultiPointMap = function( newMultiPointMapBoolean ) {
				if (typeof newMultiPointMapBoolean !== "boolean") {
					throw new Error ("setMultiPointMap expected 1 boolean input");
				}
				isMultipointMap = newMultiPointMapBoolean;
			};
			
			// Execute initialisation script
			this.init(newId);
		};
		
		// Map non-privaleged functions
		mapConstructor.prototype = {
			
			// Configuration method
			init: function(newId){
				
				// set the ID
				this.setID( newId );
				
				// Variables
				var that = this;

				this.fetchVcardDetails();	
				
				// If this is a 'click map', load the map on the click event if it doesnt exist,
				// Otherise load the map when document is ready
				if (this.isClickMap()) {
					this.$getMap().bind("click", function(){
						if (!that.$getMap().hasClass('MSVE_MapContainer')) {
							that.loadMap();
						}
					});
				} else {		
					$(document).ready(function(){
						that.loadMap();
					});
				}
			},
			createMap: function(){
				var map = new VEMap( this.getID() );
				this.getMap = function(){
					return map;
				};
			},
			/**
			 * This function loads the map and adds any pins found on page
			 */
			loadMap: function(){
				this.drawMap();
				this.addPushPins();
			},			
			/**
			 * Collects vcards on page, pushes the vcard details to the vcards parameter.
			 * For a single vcard, the VElatLong param gets set as a VELatLong.
			 * If there are multiple vCards, the VELatLong gets set as an array of VELatLongs
			 */
			fetchVcardDetails: function(){
				var tempVcards = [],
					that = this;
				
				$('#mainContent .vcard, .layoutAreaLightbox .vcard').each(function(i){
					var that = $(this),

						// Helper function to fetch the text inside a vcard selector
						fetch = function( selector ){
							var theFetch = that.find( selector ),
								fetchedText = "";
								
							if ( theFetch.length > 1) {
								for (var i = 0; i < theFetch.length; i++) {
									fetchedText += $(theFetch[i]).text() + "<br />";
								}
							} else {
								fetchedText = that.find( selector ).text();
							}
							return fetchedText !== "" ? fetchedText : null;
						};
					
					if ((fetch('.latitude') === null || fetch('.longitude') === null)) {
						return true;  // Don't push this vcard, continue to next one
					}
					var vcard = {
							name: fetch('.fn'),
							note: fetch('.note'),
							address: fetch('.adr'),
							tel: fetch('.tel'),
							latLong: new VELatLong(
										parseFloat( fetch('.latitude') ),
										parseFloat( fetch('.longitude') )
									)
						};
					tempVcards.push( vcard );
				});
				
				
				if(tempVcards.length === 1) {
					that.setParam('VELatLong', tempVcards[0].latLong);
				}
				else if (tempVcards.length > 1) {
					var tempLatLongs = [];
					for (var i = 0; i < tempVcards.length; i++) {
						tempLatLongs.push(tempVcards[i].latLong);
					}
					this.setMultiPointMap( true );
					this.setParam('VELatLong', tempLatLongs);
				}
				
				this.setParam('vcards', tempVcards);
			},
			/**
			 * Add all pins to the map
			 */
			addPushPins: function( ){
				var latLon = this.getParam('VELatLong'),
					vcards = this.getParam('vcards'),
					initLatLon = latLon.length > 0 ? latLon[0] : latLon,
					
					pushPinParams = {
						shapeType: VEShapeType.Pushpin,
						VEMapViewSpecification: new VEMapViewSpecification(
							initLatLon, // VELatLong
							this.getParam("zoom"),  // Zoom
							1000,  // Altitude
							-90,  // Pitch
							0  // Heading
						)
					},
					
					shapeLayer = new VEShapeLayer(),
					that = this,
					mapViewType = this.isMultiPointMap() ? latLon : pushPinParams.VEMapViewSpecification,
					
					// Creates pins
					createPin = function( vcard, newPinId ) {
						var shape = new VEShape( pushPinParams.shapeType, vcard.latLong ),
							desc = "",
							pinId = newPinId || "";
							
						shape.SetTitle( vcard.name );
						
						// Determine pin style
						if (that.isMultiPointMap()) {
							var pinElement = '<div class="pinStyle">' + pinId + '</div>';
							shape.SetCustomIcon(pinElement); 	
						}
						
						// Construct the pin's description field
						for (var item in vcard) {
							if (vcard[item] === null) {
								continue;
							}
							switch (item) {
								case "latLong":
									break;
								case "name":
									break;
								default:
									desc += '<p>' + vcard[item] + '</p>';
							}
						}
						
						shape.SetDescription( desc );
						shapeLayer.AddShape(shape);
					};
					
				if ( (vcards.length > 1) && (this.isMultiPointMap()) ) {
					for (var i=0; i < vcards.length; i++) {
						createPin( vcards[i], i + 1 );
					}
					shapeLayer.SetClusteringConfiguration(VEClusteringType.Grid);
				} else {
					createPin( vcards[0] );
				}
				this.getMap().AddShapeLayer(shapeLayer);
				this.getMap().SetMapView( mapViewType );
			},			
			drawMap: function(){
				this.createMap();
				this.setDimensions();
				this.setToken();
				// For more on this function see the Microsoft website:
				// http://msdn.microsoft.com/en-us/library/bb412546.aspx
				this.getMap().LoadMap(
					this.getParam("VELatLong")[0],
					this.getParam("zoom"),
					this.getParam("style"),
					this.getParam("fixed"),
					this.getParam("mode"),
					this.getParam("showSwitch"),
					this.getParam("tileBuffer"),
					this.getParam("mapOptions")
				);

				// Fix bing calculation bug that sets dashboard width to zero before CSS loaded
				$('div#MSVE_navAction_container').css("width", "");
			},
			setDimensions: function(){
				var tempHeight = $( '#' + this.getID() + ' img' ).height(),
					tempWidth = $( '#' + this.getID() + ' img' ).width(),
					height = tempHeight > 200 ? tempHeight : 200,
					width = tempWidth > 200 ? tempWidth : 200;
					
				// Multipoint map options
				if (this.isMultiPointMap()) {
					this.setHeight( $( '#' + this.getID() ).width() * 0.7 );
					this.setWidth( $( '#' + this.getID() ).width() );
				}
				// Single point map options
				else {
					this.setHeight( height );
					this.setWidth( width );
				}
			},
			isClickMap: function(){
				return this.$getMap().hasClass( this.getParam('clickMapClass') );
			},
			getWidth: function(){
				return this.$getMap().width();
			},
			getHeight: function(){
				return this.$getMap().height();
			},
			$getMap: function(){
				return $('#' + this.getID());
			},
			getHTML: function(){
				return this.$getMap.html();
			},
			setWidth: function(newWidth){
				this.$getMap().width( newWidth );
			},
			setHeight: function(newHeight){
				this.$getMap().height( newHeight );
			},
			setToken: function(){
				var className = this.$getMap().attr('class'),
					classToMatch = this.getParam('mapClass'),
					token = BTT.Utilities.getVarsFromClassName( className, classToMatch )[0];
				if (token) {
					this.getMap().SetClientToken(token);
				}
			}			
		};
		
		return mapConstructor;
	}()),
	

	init: function(){
		var that = this;
		
		function initiateMaps(){
			var $allMaps = $('[class*=JS_map(]');

			$allMaps.each(function(i){
				BTT.Maps.allMaps.maps.push( new that.Map( $(this)[0].id) );
			});	
			
		}
		BTT.Utilities.ensureBingJS( initiateMaps );
	}
	
};


/* Initialise when the DOM is ready
-------------------------------- */
$(document).ready(function(){
	BTT.Maps.init();
});



