var mapping = {
	init: function() {
		/* Initialise components for the app
		*/
		mapping.loadingDiv = document.getElementById("csmap");
		mapping.gdForm = document.getElementById("gdform");
		/*Get points we're interesting in plotting - 
		in an ideal world we'd get this from a json ws - so plug that in here:
		*/
		mapping.cspoints = cspoints;
		/*load mapping:
		 a) create a custom event
		 b) subscribe a callback for the event
		 c) try and load the MSVE api
		 The custom event is strictly speaking not required, but it seems neater
		 given the differences in the js load events of FF and MSIE.
		*/
		var onVELoad = new YAHOO.util.CustomEvent("onVELoad");
		onVELoad.subscribe(mapping.onVELoadHandler);
		//V4: http://maps.live.com/veapi.ashx?v=1.3.1115150037.31
		//V3: http://maps.live.com/veapi.ashx?v=1.3.0908172755.52
		mapping.loadJS('http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6', onVELoad);
  
        mapping.createDestinations(cspoints);
        YAHOO.util.Event.addListener(mapping.gdForm, 'submit', mapping.plotRoute);
        YAHOO.util.Event.addListener(mapping.gdForm, 'reset', mapping.reset);
	},
    
	loadJS: function(file, event){    
		var head = document.getElementsByTagName("head").item(0);
		var js = document.createElement("script");
		js.id = "vemap_api";
		js.type = "text/javascript";
		js.src = file;
		head.appendChild(js)
		js.onload = function(){event.fire()};
		js.onreadystatechange = function(){ 
			if (js.readyState == "complete" || js.readyState=='loaded') {
				event.fire();
			}
		};
	},
   	
	onVELoadHandler: function(type, args){
		// Set up the animation on the results div.
		var loadingFadeOut = new YAHOO.util.Anim(mapping.loadingDiv, {opacity: { to: 0 }}, 1.0, YAHOO.util.Easing.easeOut);
		var loadingFadeIn = new YAHOO.util.Anim(mapping.loadingDiv, {opacity: { to: 1 }}, 0.5, YAHOO.util.Easing.easeIn);
		//doing a lot this anonymous function, but it's easier given the "fade in"
		loadingFadeOut.onComplete.subscribe(function() {
			mapping.loadingDiv.innerHTML = '';
			mapping.firefoxHack();
			mapping.map = new VEMap('csmap');
			mapping.map.LoadMap(new VELatLong(-34.031999, 151.071539), 14 ,'r' , false);     
			mapping.map.ShowDashboard();
			mapping.map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);
			mapping.map.ShowDisambiguationDialog(true);
			mapping.addPins(mapping.cspoints);
			loadingFadeIn.animate();
		});
		loadingFadeOut.animate();
	},
    
	addPins: function(points){
		/*Given a points dictionary (hopefully from a json ws) create push pins for each point
	    and set the map zoom so all pushpins are visible.
	    */
		var pinID = 1;
		var latlongs = [];
		for (var i in points.pins){
			latlongs[i] = new VELatLong(points.pins[i].lat, points.pins[i].long);
			var pin = new VEPushpin(pinID, latlongs[i], points.pins[i].icon_url, points.pins[i].title, points.pins[i].details); 
			mapping.map.AddPushpin(pin);
			pinID++;
		}
		mapping.map.SetMapView(latlongs);
	},
    
	firefoxHack: function (){
		// If the browser is Firefox get the version number
		var ffv = 0;
		var ffn = "Firefox/"
		var ffp = navigator.userAgent.indexOf(ffn);
		if (ffp != -1) ffv = parseFloat(navigator.userAgent.substring(ffp + ffn.length));
		// If we're using Firefox 1.5 or above override the Virtual Earth drawing functions to use SVG
		if (ffv >= 1.5) {
			Msn.Drawing.Graphic.CreateGraphic=function(f,b) { return new Msn.Drawing.SVGGraphic(f,b) }
		}
	},
	
	createDestinations: function(points){
		var dest = document.getElementById("destination_container");
		var destinationInfo = [];
		if (points.pins.length > 1){
			//more than one choice so make a select
			var select = document.createElement('select');
			select.id = "destination_input";
			select.className = "field";
			for (var i in points.pins){
				var opt = document.createElement('option');
				opt.value = points.pins[i].ID;
				opt.innerHTML = points.pins[i].title;
				select.appendChild(opt);
			}
			dest.appendChild(select);
		}
		else{
			//only one choice so no select
			var hidden = document.createElement("input");
			hidden.type = "hidden";
			hidden.id = "destination_input";
			hidden.value = points.pins[0].ID;
			var label = document.createElement("p");
			label.innerHTML = points.pins[0].title;
			dest.appendChild(hidden);
			dest.appendChild(label);
		}
	},
	
	plotRoute: function(e){
		YAHOO.util.Event.preventDefault(e);
		//scrub directions and errors
		mapping.reset(true);
		var address_input = document.getElementById("address_input").value;
		var location_input = document.getElementById("location_input").value
		var errors = false;
		if (address_input.split(/\s/).join('') == ''){
			errors = true;
			mapping.showErrors("address_input");
		}
		if (location_input.split(/\s/).join('') == ''){
			errors = true;
			mapping.showErrors("pcautocomp");
		}
		if (!errors){
			var origin = [address_input, location_input, 'Australia'];
			mapping.map.Clear();
			var dest = "";
			var dest_input = document.getElementById("destination_input");
			try {
				dest = dest_input.options[dest_input.selectedIndex].value;
			}
			catch (e){
				dest = dest_input.value;
			}
			mapping.map.GetRoute(origin.join(", "), dest , VEDistanceUnit.Kilometers, 
			VERouteType.Quickest, mapping.onGotRouteHandler);
		}
	},
	
	onGotRouteHandler: function(route){
		var directions_container = document.getElementById('directions_container');
		var routeinfo = '<table><thead><tr><th></th><th>Directions</th><th class="details">Km\'s</th></tr></thead><tbody>';		
		var steps=[];
		var len = route.Itinerary.Segments.length;
		for(var i = 0; i < len ;i++)
		{
			var extra = " ";
			if (route.Itinerary.Segments[i].Instruction == "Start at "){
				extra += route.StartLocation;
			}
			else if (route.Itinerary.Segments[i].Instruction == "Arrive at "){
				extra += cspoints.pins[0].title;
			}
			steps.push('<tr><td class="step">', i+1, "</td>");
			steps.push("<td>", route.Itinerary.Segments[i].Instruction,  extra, "</td>");
			steps.push('<td class="details">(', route.Itinerary.Segments[i].Distance, ") ", route.Itinerary.DistanceUnit, "</td></tr>");
		}
		routeinfo += steps.join("") + '</tbody></table>';
		routeinfo += ['<div class="result">Total distance: ', route.Itinerary.Distance,  " ", route.Itinerary.DistanceUnit, " | Total time: ", route.Itinerary.Time,  "</div>"].join("");
		directions_container.innerHTML = routeinfo;
		directions_container.style.display = "block";
	},
	
	showErrors: function(error){
		var note_container = document.getElementById(error + "_note");
		var err_div = document.createElement("div");
		YAHOO.util.Dom.addClass(err_div, 'error');
		var err_img = document.createElement("img");
		err_img.src = "images/icon_alert.gif";
		err_img.alt = "This field is required.";
		err_div.appendChild(err_img);
		note_container.parentNode.insertBefore(err_div, note_container);
	},
	
	reset: function(e){
		document.getElementById("directions_container").style.display = "none";
		document.getElementById("directions_container").innerHTML = "";
		var form_fields = mapping.gdForm.getElementsByTagName('div');
		for(var i=0; i<form_fields.length; i++) {
			if(YAHOO.util.Dom.hasClass(form_fields[i], 'error')) {
				form_fields[i].parentNode.removeChild(form_fields[i]);
			}
  		}
  		if (e != true){
  			mapping.map.Clear();
  			mapping.addPins(mapping.cspoints);
  		}
	},
	
	unloadMap: function() 
	{
		//dispose of map
		if (mapping.map != null)
		{
			mapping.map.Dispose();
		}
	} 
};

YAHOO.util.Event.addListener(window, 'load', mapping.init);
YAHOO.util.Event.addListener(window, 'unload', mapping.unloadMap);