///////////////////////////////////////////////////////////////////////////////
//	Tools JS Actions
///////////////////////////////////////////////////////////////////////////////

//Tools Common

var MapControlPanel = null;

core.action.ToolsCommon = (function () {
	var ToolsCommon = core.action.AbstractAction(/.*/, ['tools']);

	ToolsCommon.initialize = function () {

		var hash = window.location.hash;
	
		window.setInterval(function () {
			if(window.location.hash !== hash) {
				hash = window.location.hash;
				ViewHandler.setState(core.env.getHash('view', hash));
			}
		}, 500);

		$('a','li#tools-navigation-map').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('map');
			core.ui.tools.State.view = 'map';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('map');
		});

		$('a','li#tools-navigation-comparemodels').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('comparison');
			core.ui.tools.State.view = 'comparison';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('comparison');
		});

		$('a','li#tools-navigation-salesrep').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('sales');
			core.ui.tools.State.view = 'sales';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('sales');
		});
		
		$('a#primary-nav-tools-map').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('map');
			core.ui.tools.State.view = 'map';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('map');
		});

		$('a#primary-nav-tools-comparemodels').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('comparison');
			core.ui.tools.State.view = 'comparison';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('comparison');
		});

		$('a#primary-nav-tools-salesrep').click(function (event) {
			event.preventDefault();
			//ViewHandler.setState('sales');
			core.ui.tools.State.view = 'sales';
			core.ui.tools.updateHashView();
			ViewHandler.trackView('sales');
		});

		var JSONHandler,
			ControlPanel,
			GoogleMapsSearchBox = core.ui.tools.GoogleMapsSearchBox($('#loc'), {}),
			Legend;
						
		JSONHandler = core.util.ServiceHandler({
			'url': core.env.aircraftService + 'GetRangeMapData',
			'data': '{}',
			'dataType': 'json'
		});
		

		JSONHandler.bind('loaded', function (event) {
			var data = JSONHandler.data;

			MapControlPanel = core.ui.tools.ControlPanel(data, $('#model-groups'), $('#range_map-cp-group-model'), {});
			Map = core.ui.tools.RangeFinder.Map($('#mapcontainer').get(0), {});
			core.ui.tools.Map = Map;

			MapControlPanel.bind('maxAircraftSelected', function(event, selectedAircraft) {
				//console.error("Only 3 Aicraft may be selected.");
			});

			MapControlPanel.bind('aircraftSelected', function(event, selectedAircraft, aircraft) {
				drawRanges(selectedAircraft);
			});

			MapControlPanel.bind('aircraftUnselected', function(event, selectedAircraft, aircraft) {
				drawRanges(selectedAircraft);
			});

			MapControlPanel.bind('passengersUpdated', function(event, selectedAircraft, aircraft) {
				drawRanges(selectedAircraft);
			});
			
			GoogleMapsSearchBox.bind('locationChange', function(event) {
				drawRanges(MapControlPanel.getSelectedAircraft());
			});
			
			GoogleMapsSearchBox.bind('redrawRanges', function(event, selectedAircraft) {
				drawRanges(selectedAircraft);
			});
			

			ViewHandler.setState(core.ui.tools.State.view);


			for(var i=0, j=core.ui.tools.State.aircraft.length; i < j; i++) {
				MapControlPanel.selectAircraftById(core.ui.tools.State.aircraft[i]);
			}
			
		});



		function drawRanges(selectedAircraft) {
			var i,
				aircraft,
				lineWeightAdj = 1;
			var lineWeight = 1.5 + selectedAircraft.length*lineWeightAdj;
			Map.clear();
			Map.resetZoomLevel();

			// Draw ranges from largest to smallest
			selectedAircraft.sort(function(a, b) {
			   var compA = a.getRangeKM();
			   var compB = b.getRangeKM();
			   return (compA > compB) ? -1 : (compA < compB) ? 1 : 0;
			})
			$.each(selectedAircraft, function(idx, aircraft) { 
				Map.drawRange(GoogleMapsSearchBox.getLocation(), aircraft.getRangeKM(), {'lineColor': aircraft.selectedColor,'lineWeight': lineWeight});
				lineWeight = lineWeight - lineWeightAdj;
			});

			Map.initializeMapView(GoogleMapsSearchBox.getLocation(), Map.getZoomLevel());
		}

		var MeasurementUnitList = new core.ui.List({
					'list': $('#measurement-unit ul')
				});
		$('#measurement-unit ul a').click(function (event) {
			event.preventDefault();
		});
		
		MeasurementUnitList.bind('itemSelected', function(event, item, index) {
			ViewHandler.setMeasurement();
		});


	}
	return ToolsCommon;

}());

core.ui.tools = {}
core.ui.tools.Map = {}

core.ui.tools.ViewHandler = function (settings) {
	var ViewHandler = new Class(),
		defaults = {},
		state,
		SecondaryNavList = new core.ui.List({
			'list': $('ul#section-navigation'),
			'preventDefault': true,
			'autoSelectDefault': false
		});

	settings = $.extend(true, defaults, settings);

	state = settings.state;

	function init () {
		// perhaps establish onLoad/initial view here if a hash param is present?
		return ViewHandler;
	}
	
	ViewHandler.getMeasurement = function() {
		return $('#measurement-unit ul li.selected a').html();
	}
	
	ViewHandler.setMeasurement = function() {
		// the table cell 'display' value varies from browser to browser, 
		// use a known element to determine the value
		var displayProperty = $('table.specs tbody tr th').eq(0).css('display');
		switch($('#measurement-unit ul li.selected a').html()) {
			case 'US':
				$('td.measure-metric').css({'display': 'none'});
				$('td.measure-standard').css({'display': displayProperty});
				break;
			case 'METRIC':
				$('td.measure-standard').css({'display': 'none'});
				$('td.measure-metric').css({'display': displayProperty});
				break;
			default:
				$('td.measure-metric').css({'display': 'none'});
				$('td.measure-standard').css({'display': displayProperty});
				break;
		}
	}

	ViewHandler.viewMap = function() {

		$('li#measurement-unit').css({'display': 'none'});
		$('li#tools-controlpanel-search').css({'display': 'block'});
		$('li#model-groups').css({'display': 'block'});
		$('div.payload.selected' ,$('li#model-groups')).css({'display': 'block'});

		$('div#content-comparemodels').css({'display': 'none'});
		$('div#content-salesrep').css({'display': 'none'});
		$('div#content-map').css({'display': 'block'});
		core.ui.tools.Map.GoogleMap().checkResize();
		MapControlPanel.trigger('redrawRanges', [MapControlPanel.getSelectedAircraft()]);
	}

	ViewHandler.viewComparison = function() {

		$('li#model-groups').css({'display': 'block'});
		$('div.payload' ,$('li#model-groups')).css({'display': 'none'});
		$('li#tools-controlpanel-search').css({'display': 'none'});
		$('li#measurement-unit').css({'display': 'block'});
		
		$('div#content-map').css({'display': 'none'});
		$('div#content-salesrep').css({'display': 'none'});
		$('div#content-comparemodels').css({'display': 'block'});
	}
	
	ViewHandler.viewSales = function() {
	
		$('li#measurement-unit').css({'display': 'none'});
		$('li#model-groups').css({'display': 'none'});
		$('li#tools-controlpanel-search').css({'display': 'none'});

		$('div#content-map').css({'display': 'none'});
		$('div#content-comparemodels').css({'display': 'none'});
		$('div#content-salesrep').css({ 'display': 'block' });

		//hide and show appropriate sales rep divs
		$('div#salesrep-map').css({ 'display': 'block' });
		$('div#salesrep-model').css({ 'display': 'none' });
		$('div#salesrep-results').css({ 'display': 'none' });
	}

	ViewHandler.setState = function (s) {
			state = s;
			ViewHandler.trigger('stateChanged', [state]);
			core.ui.tools.State.view = s;
			switch (state) {
				case 'map':
					SecondaryNavList.select($('li#tools-navigation-map'));
					ViewHandler.viewMap();
					break;
				case 'comparison':
					SecondaryNavList.select($('li#tools-navigation-comparemodels'));
					ViewHandler.viewComparison();
					break;
				case 'sales':
					SecondaryNavList.select($('li#tools-navigation-salesrep'));
					ViewHandler.viewSales();
					break;
				default:
					SecondaryNavList.select($('li#tools-navigation-map'));
					ViewHandler.viewMap();
			}
		core.ui.tools.updateHashView();	
		
	}

	ViewHandler.getState = function () {
		return state;
	}

	ViewHandler.trackView = function (v) {
		// remove hash, prefix ending with //, and server name leading up to first /
		var currenturl = window.location.toString().replace(window.location.hash.toString(),'');
		currenturl = currenturl.substr(currenturl.indexOf('//')+2);
		currenturl = currenturl.substr(currenturl.indexOf('/'));
		// add the correct hash back in
		currenturl = currenturl + '#' + v;
		pageTracker._trackPageview(currenturl);
}

	return init();

};

core.ui.tools.RangeFinder = {}
core.ui.tools.RangeFinder.Map = function (element, options) {

	var Map = $(this),
		GoogleMap, 
		zoomLevel,
		defaultOptions = {
			'minZoom': 1,
			'maxZoom': 4,
			'defaultZoomLevel': 2
		};

	options = $.extend(true, {}, defaultOptions, options);
	options.location = new GLatLng(37.686980, -97.335579);	

	Map.getZoomLevel = function() {
		if(zoomLevel) {
			return zoomLevel;
		} else {
			return options.defaultZoomLevel;
		}
	}
	
	Map.setZoomLevel = function(zoom) {
		zoomLevel = zoom;
	}
	
	Map.resetZoomLevel = function(zoom) {
		zoomLevel = options.defaultZoomLevel;
	}

	GoogleMap = function () {
		var GoogleMap = {},
			isBrowserCompatible = GBrowserIsCompatible(),
			mapTypes,
			i = 0;

			if (isBrowserCompatible) {
				GoogleMap = new GMap2(element, {backgroundColor: '#000'});
				mapTypes = GoogleMap.getMapTypes();

				for (i = 0; i< mapTypes.length; i = i + 1) {
					mapTypes[i].getMinimumResolution = function() {
						return options.minZoom;
					};
					mapTypes[i].getMaximumResolution = function() {
						return options.maxZoom;
					};
				}

				GoogleMap.setCenter(options.location, Map.getZoomLevel());
				
				GoogleMap.addControl(new GSmallZoomControl3D());
				//map.addControl(new GLargeMapControl3D());
				//map.addControl(new GScaleControl());
				//map.addControl(new GMenuMapTypeControl());
				
				// Add event listener for mouse click
				//GEvent.addListener(map,'click', function(overlay, point) { drawStart(point); } );
				//map.getDragObject().setDraggableCursor('crosshair');
			}

			return GoogleMap;

	}(options.location, options.zoomLevel);
	// Encode a signed number in the encode format.
	function encodeSignedNumber(num) {
	  var sgn_num = num << 1;

	  if (num < 0) {
	    sgn_num = ~(sgn_num);
	  }

	  return(encodeNumber(sgn_num));
	}
	// Encode an unsigned number in the encode format.
	function encodeNumber(num) {
	  var encodeString = "";

	  while (num >= 0x20) {
	    encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
	    num >>= 5;
	  }

	  encodeString += (String.fromCharCode(num + 63));
	  return encodeString;
	}
	function createEncodedPolyline(points, lineColor, lineWeight) {
	  var i = 0;

	  var plat = 0;
	  var plng = 0;

	  var encoded_points = "";
	  var encoded_levels = "";

	  for(i = 0; i < points.length; ++i) {
	    var point = points[i];
	    var lat = point.lat();
	    var lng = point.lng();
	    var level = 3;

	    var late5 = Math.round(lat * 1e5);
	    var lnge5 = Math.round(lng * 1e5);

	    dlat = late5 - plat;
	    dlng = lnge5 - plng;

	    plat = late5;
	    plng = lnge5;

	    encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
	    encoded_levels += encodeNumber(level);
	  }

	  if (points.length > 1) {
		return GPolyline.fromEncoded({
			color: lineColor,
			weight: lineWeight,
			opacity: 1,
			points: encoded_points,
			zoomFactor: 32,
			levels: encoded_levels,
			numLevels: 4
		});
	  } else {
	    return null;
	  }

	}
	function createEncodedPolygon(points, fillColor) {
	  var i = 0;

	  var plat = 0;
	  var plng = 0;

	  var encoded_points = "";
	  var encoded_levels = "";

	  for(i = 0; i < points.length; ++i) {
	    var point = points[i];
	    var lat = point.lat();
	    var lng = point.lng();
	    var level = 3;

	    var late5 = Math.round(lat * 1e5);
	    var lnge5 = Math.round(lng * 1e5);

	    dlat = late5 - plat;
	    dlng = lnge5 - plng;

	    plat = late5;
	    plng = lnge5;

	    encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
	    encoded_levels += encodeNumber(level);
	  }

	  if (points.length > 1) {
		var encodedPolylines = Array();
		encodedPolylines.push({color: fillColor,
									  weight: 0,
									  points: encoded_points,
									  zoomFactor: 32,
									  levels: encoded_levels,
									  numLevels: 4
									 });
	    return GPolygon.fromEncoded({polylines:encodedPolylines, fill:true, color:fillColor, opacity:.33, outline:false});
	  } else {
	    return null;
	  }

	}
	function cleanUp () {
		// Move polylines to topmost layer (higher z-index) after redraw
		// because of a bug with Google Maps that typically occurs
		// following a change of zoom or dragging where lines fall underneath polygons

		var $pathElements,
				baseIndex = 1000;  // since Google Maps might change this default z-index, we'll capture it from other svg elements
		
		// Firefox: find <svg> child elements called <path> that have 
		//          a 'stroke-width' attribute (fill paths don't have a stroke)
		$pathElements = $('path[stroke-width]')
		if ($pathElements.length > 0) {
			$pathElements.each(function(index, item) {
				var $this = $(item);
			
				$this.parent().css({
					'zIndex':  baseIndex + 50
				})

			})
		}

		// IE: find <stroke> elements belonging to <shape> elements where the 
		//     parent <shape> element does not contain a <fill> child (<stroke> sibling)
		$pathElements = $('shape:has(stroke)').filter(function(index) {
			if ($(this).find("fill").length > 0) {
				return false;
			} else {
				return true;
			}
		});

		if ($pathElements.length > 0) {
			$pathElements.each(function(index, item) {
				var $this = $(item);

				$this.css({
					'zIndex': baseIndex + 50
				})

			})
		}
		
		
		//yield the browser
		window.setTimeout(function () {}, 0);

	}
	function drawRange (point, range, options) {
		var defaultOptions = {
			'lineColor': '#000',
			'fillColor': '#788498',
			'numberOfSpokes': 72,
			'lineWeight': 2
			},
			isSelfContained = true,
			linePoints = [],
			fillPoints = [],
			fillPointSets = [],
			boxTop,
			boxBottom,
			midPoint,
			i = 0,
			slices,
			boxes;
	
		options = $.extend(true, {}, defaultOptions, options);

		function Point (latitude, longitude, type) {
			if (type === 'simple'){
				return new LatLon(latitude, longitude);
			} else {
				return new GLatLng(latitude, longitude);
			}
			
		}

		function Spoke (iteration, numberOfSpokes, range) {
			var Spoke = {},
				bearing = iteration * (360 / options.numberOfSpokes) + '°',
				polyPoint,
				isMiddleSpoke = (iteration === numberOfSpokes/2);


			Spoke.startPoint = Point(point.lat(), point.lng(), 'simple');
			Spoke.endPoint = Spoke.startPoint.destPoint(bearing.parseDeg(), parseFloat(range));
			Spoke.latitude = Spoke.endPoint.lat.toString();
			Spoke.longitude = Spoke.endPoint.lon.toString();
			polyPoint = Point(Spoke.latitude, Spoke.longitude);

			linePoints.push(polyPoint);
			fillPoints.push(polyPointAdapter(polyPoint));

			function polyPointAdapter (polyPoint) {
				var pointSpread,
					min = 179.9,
					max = 180.1;
					increment = 0.1;
				// Resolve glitch with first point or first point of second 
				// half (southern hemisphere) stretching 180 degrees
				// Adjust the point by one-tenth of a degree inward to
				// produce reliable rendering results
				if (iteration === 0 || isMiddleSpoke) {
					pointSpread = Number(polyPoint.lng()) - Number(point.lng());
					if ((pointSpread > min) && (pointSpread < max)) {
						polyPoint = Point(polyPoint.lat(), (Number(polyPoint.lng()) + increment));
					}
				}

				return polyPoint;
			}

			// if at midpoint, the midpoint is not vertically aligned with the starting point
			// then this range region is an open ended curve rather than a closed shape
			if (isMiddleSpoke && (linePoints[0].lng().toFixed(10) != Number(Spoke.longitude).toFixed(10))) {
				// range region is not a self contained oval, but a wave near the north or south pole

				isSelfContained = false;

				(function () {
					// Google maps doesn't go all the way to +/- 90
					var upperRenderLimit = 85.05,
						lowerRenderLimit = -85.05; 

					if (point.lat() < 0) {
						// Southern hemisphere
						midPoint = new Point(Spoke.latitude, point.lng());
						// fill box needed for midpoint down to latitude of midpoint
						boxTop = Spoke.latitude;
						boxBottom = lowerRenderLimit;
						
					} else {
						// Northern hemisphere
						midPoint = new Point(fillPoints[0].lat(), point.lng());
						// fill box needed for north pole down to latitude of first point
						boxTop = upperRenderLimit;
						boxBottom = fillPoints[0].lat();
					}

				})();
			}
	
		}

		// loop through and gather spokes
		for (i; i <= options.numberOfSpokes; i = i + 1) {
			Spoke(i, options.numberOfSpokes, range);
		}

		if (isSelfContained) {
			fillPointSets.push(fillPoints);
		} else {
			slices = pieFactory(4);
			for (i in slices) {
				fillPointSets.push(slices[i]);
			}
			
			boxes = boxFactory(4);
			for (i in boxes) {
				fillPointSets.push(boxes[i]);
			}

		}

		draw();

		function pieFactory (numberOfPiesPerGroup) {
			// create collection of polygons for fill
			/*
				polygon is likely too large to be rendered in Google Maps without vector drawing issues
				draw as individual pieces of pie instead of one large polygon
				bigger groups pies = faster rendering
				smaller groups of pies = fewer google map glitches
			*/

			var i,
				pie = [],
				slice = [],
				n;

			for (i = numberOfPiesPerGroup; i <= fillPoints.length - 1; i = i + numberOfPiesPerGroup) {
				slice.push(midPoint);

				for (n = numberOfPiesPerGroup; n >= 0; n = n - 1) {
					slice.push(fillPoints[i - n]);
				}
				slice.push(midPoint);
				pie.push(slice);
				slice = [];
			}
			return pie;
		}

		// makes boxes of boxes to fill gaps above or below openend plots
		function boxFactory (numberOfBoxes) {
			var boxWidth = 360 / numberOfBoxes,
				offset = 0,
				boxes = [],
				box = [],
				i = 0;

			if (boxTop > boxBottom) {
				for (offset; offset < 360; offset = offset + boxWidth) {
					box.push(Point(boxTop, offset));
					box.push(Point(boxBottom, offset));
					box.push(Point(boxBottom, boxWidth + offset));
					box.push(Point(boxTop, boxWidth + offset));
					box.push(Point(boxTop, offset));
					boxes.push(box);
					box = [];
				}
			}

			return boxes;

		}

		// Draw range fill
		function draw() {
			var i = 0,
				encodedPolygon,
				encodedPolyline,
				initialZoom = calculateInitialZoom();
			for (i=0; i <= fillPointSets.length - 1; i = i + 1) {

				encodedPolygon = createEncodedPolygon(fillPointSets[i], options.fillColor);

				/*
				GEvent.addListener(encodedPolygon,'click',function(point) {
					drawStart(point);
				});
				*/

				GEvent.addListener(encodedPolygon, 'redraw', function(point) {
					//trigger didn't work
					//Map.trigger('polygonRedrawComplete', []);
					cleanUp();
				});

				if (encodedPolygon) {
					GoogleMap.addOverlay(encodedPolygon);
				}

			}


			//  Draw range line
			encodedPolyline = createEncodedPolyline(linePoints, options.lineColor, options.lineWeight);
			/*
			GEvent.addListener(encodedPolyline,'click',function(point) {
				drawStart(point);
			});
			*/
			if (encodedPolyline) {
				GoogleMap.addOverlay(encodedPolyline);
			}
			
			if (initialZoom < Map.getZoomLevel()) {
				Map.setZoomLevel(initialZoom);
			}


			// handle map view: zoom and centering
			function calculateInitialZoom () {
				var minimumZoom = 2,
					bounds,
					i = 0,
					boundsZoom;

				if (isSelfContained === false) {
						return minimumZoom;
				} else {
					// auto zoom and center based upon points in linePoints array
					bounds = new GLatLngBounds();
					for (i; i < linePoints.length; i = i + 1) {
						bounds.extend(linePoints[i]);
					}

					boundsZoom = GoogleMap.getBoundsZoomLevel(bounds);

					if (boundsZoom < minimumZoom) {
						return minimumZoom;
					} else {
						return boundsZoom;
					}

				}
			}
			
		}

		Map.trigger('rangeDrawingComplete', []);
	}

	Map.initializeMapView = function (point, zoom) {
		var aircraftIcon = new GIcon(G_DEFAULT_ICON);
		aircraftIcon.image = '/assets/images/global/common/tools/map.aircraft.icon.png';
		aircraftIcon.shadow = '/assets/images/global/common/tools/map.aircraft.shadow.png';
		aircraftIcon.iconSize = new GSize(40, 40);
		aircraftIcon.shadowSize = new GSize(40, 40);
		aircraftIcon.iconAnchor = new GPoint(19, 19);
		aircraftIcon.infoWindowAnchor = new GPoint(38, 2);
		var markerOptions = { icon:aircraftIcon };

		// Add selected point marker
		var marker = new GMarker(point, markerOptions);
		/*var marker = new GMarker(point, {draggable: true});
		GEvent.addListener(marker, 'dragend', function(point) {
			drawStart(point);
		});
		*/
		GoogleMap.addOverlay(marker);

		// Set map center point and zoom level
		GoogleMap.setCenter(point, zoom);
	};
			
	Map.drawRange = function (point, range, options) {
		return drawRange(point, range, options);
	};

	Map.GoogleMap = function () {
		return GoogleMap;
	}

	Map.cleanUp = function () {
		return cleanUp();
	}
	
	Map.clear = function () {
		GoogleMap.clearOverlays();
	}

	Map.bind('rangeDrawingComplete', function () {
		cleanUp();
	});

	return Map;

}
core.ui.tools.ControlPanel = function (data, $element, $model, options) {
	var ControlPanel = $(this),
		selectedAircraft = [],
		maxAircraftSelected = false,
		aircraft = [],
		defaultOptions = {
			'groupBy': 'brand',
			'maxAircraftSelected': 3
		};

	options = $.extend(true, {}, defaultOptions, options);

	function initialize (data) {
		var i,
			j = data.aircrafts.aircraft.length;

		for( i = 0; i < j; i = i + 1 ) {
			aircraft.push(AircraftFactory(data.aircrafts.aircraft[i]));
		}


		//render aircraft
		function renderControlPanel() {
			var $HTMLModel = $model;

			if ($HTMLModel.hasClass('rangemap')) {
				createRangeMapGroups();
			} else if ($HTMLModel.hasClass('comparison')) {
				//Create Comparison Groups
			}


			function createRangeMapGroups() {
				var $HTML,
					$list,
					$aircraft,
					$passengers,
					$crewText,
					$label,
					$group,
					groups = (function () {
						var groups = [],
							i;

						for(i = 0; i < aircraft.length; i = i + 1) {
							groups.push(aircraft[i][options.groupBy]);
						}

						groups = core.util.Array.unique(groups);

						return groups;

					})(),
					i, //group
					n, // aircraft
					x; //passenger


				for(i = 0; i < groups.length; i = i + 1) {

					$HTML = $HTMLModel.clone();
					$group = $('.group', $HTML);
					$group.html(groups[i]);
					$list = $('ul', $HTML);

					for(n = 0; n < aircraft.length; n = n + 1) {
						if(groups[i] === aircraft[n][options.groupBy]) {
							$aircraft = $('.group-item', $HTML)
								.eq(0)
								.clone()
								.attr({'id': 'group-item-' + aircraft[n].id});

							$('.model', $aircraft).html(aircraft[n].model);
							
							$crewText = $('span.crewtext', $aircraft);
							$crewText.html(aircraft[n].pilots + $crewText.html());

							for (x = 0; x < aircraft[n].ranges.range.length; x = x + 1) {
								$passengers = $('ol.passengers', $aircraft);
								$label = $('<li id="' + aircraft[n].id + '_' + x + '" class="' + aircraft[n].id + '"><a href="#">' + 
									aircraft[n].ranges.range[x].passengers +
									'</a></li>');
								if (Number(aircraft[n].ranges.range[x].passengers) == Number(aircraft[n].selectedPassengers)) {
									$label.addClass('selected');
								}
								$passengers.append($label);
							}
							
							$('.select-toggle', $aircraft).attr({'id': 'select-toggle-' + aircraft[n].id});
							$('.payload', $aircraft).hide();
							$list.append($aircraft);



						}
					}

					$('.group-item', $HTML).eq(0).remove();
					$element.append($HTML.html());

				}
				
				$('ol.passengers').each(function (index, item) {
					var List = new core.ui.List({'list': $(item)});
					List.bind('itemSelected', function (event, item, index) {
						var thisAircraft;
						thisAircraft = ControlPanel.getAircraftById(item.attr('class').split(' ')[0]);
						thisAircraft.setSelectedPassengers($('a', item).html());
						ControlPanel.updateLegendPayload(thisAircraft);
						ControlPanel.trigger('passengersUpdated', [selectedAircraft, thisAircraft]);
					});
				});

				$('ol.passengers a').click(function (event) {
					event.preventDefault();
				});
					

				$('.select-toggle, .model', $element).click(function (event) {
					var $this = $(this),
						aircraft,
						i,
						id = $this.attr('id').replace('select-toggle-', '');

					event.preventDefault();
					aircraft = ControlPanel.getAircraftById(id);

					if (aircraft.selected) {
						ControlPanel.unselectAircraftById(aircraft.id);
					} else if(aircraft.selected === false && maxAircraftSelected  === false) {
						ControlPanel.selectAircraftById(aircraft.id);
						core.ui.tools.updateHashAircraft();
						ControlPanel.trigger('aircraftSelected', [selectedAircraft, aircraft]);
					}
					//core.ui.tools.State.aircraft = s;
					//core.ui.tools.updateHash();

				});

			}

		};

		renderControlPanel();

		return ControlPanel;

	}

	function AircraftFactory (data) {
		var Aircraft = {
			'selectedPassengers': 1,
			'selectedColor':'#000',
			'selected': false
		};

		Aircraft = $.extend(true, {}, Aircraft, data);

			//return Aircraft.selectedPassengers;
		//}

		Aircraft.setSelectedPassengers = function(int) {
			int = parseInt(int);
			Aircraft.selectedPassengers = int;
			return Aircraft.selectedPassengers;
		}
		
		Aircraft.getSelectedColor = function() {
			return Aircraft.selectedColor;
		}

		Aircraft.setSelectedColor = function(color) {
			Aircraft.selectedPassengers = color;
			return Aircraft.selectedColor;
		}

		Aircraft.getRangeKM = function () {
			var i;
			
			for(i = 0; i < this.ranges.range.length; i = i + 1) {
				if(Number(this.ranges.range[i].passengers) === Number(this.selectedPassengers)) {
					return Number(this.ranges.range[i].nauticalmiles) * 1.85200;
				}
			}
		}
		
		Aircraft.getRangeMI = function () {
			var i;
			
			for(i = 0; i < this.ranges.range.length; i = i + 1) {
				if(Number(this.ranges.range[i].passengers) === Number(this.selectedPassengers)) {
					return Number(this.ranges.range[i].nauticalmiles) * 1.15077945;
				}
			}
		}
		
		Aircraft.getRangeNM = function () {
			var i;
			
			for(i = 0; i < this.ranges.range.length; i = i + 1) {
				if(Number(this.ranges.range[i].passengers) === Number(this.selectedPassengers)) {
					return Number(this.ranges.range[i].nauticalmiles);
				}
			}
		}

		return Aircraft;
	}

	ControlPanel.getAircraftById = function (id) {
		var i,
			o;

		for(i = 0; i < aircraft.length; i = i + 1) {
			if(aircraft[i].id === id) {
				o = aircraft[i];
			}
		}
		
		if(aircraft) {
			return o;
		} else {
			throw new Error('No Aircraft with the id of "' + id + '" is present in aircraft data.')
		}

	}

	ControlPanel.getSelectedAircraft = function (aircraft) {
		return selectedAircraft;
	}

	/*ControlPanel.setSelectedAircraft = function (aircraft) {
		var i;

		for (i = 0; i < selectedAircraft.length; i = i + 1) {
			ControlPanel.unselectAircraftById(selectedAircraft[i].id);
		}

		for (i = 0; i < aircraft.length; i = i + 1) {
			ControlPanel.selectAircraftById(aircraft[i].id);
		}

	}*/

	ControlPanel.selectAircraftById = function (id) {
		var aircraft = ControlPanel.getAircraftById(id),
			model,
			selected = [];

		$('div#specs-background').css({'display': 'none'});
		
		var initialSelectionNumber = selectedAircraft.length + 1;
		
		if(selectedAircraft.length < options.maxAircraftSelected) {
			aircraft.selectedColor = ControlPanel.getAvailableColor();
			$('#select-toggle-' + id + ' .toggle').css({'backgroundColor': aircraft.selectedColor});
			$('#group-item-' + id + ' .payload').addClass('selected');

			if (ViewHandler.getState() !== 'comparison') {
				$('#group-item-' + id + ' .payload').show('slow');
			}

			aircraft.selected = true;
			selectedAircraft.push(aircraft);

//			ControlPanel.trigger('aircraftSelected', [selectedAircraft, aircraft]);

			model = $('li.aircraftlegend', $('div#range_map-legend-model')).clone();

			$(model).attr({'id': 'legend-' + aircraft.id});

			$('div.legendbox', model).css({'backgroundColor': aircraft.selectedColor});
			$('div.legendbrand', model).html(aircraft.brand);
			$('div.legendmodel', model).html(aircraft.model);
			$('img.aircraftimage', model).attr('src', '/assets/images/global/common/tools/aircraft/'+aircraft.id+'.png');
			
			$('ul#aircraftlegend').append(model);

			ControlPanel.updateLegendPayload(aircraft);
			
			var ServiceHandler = core.util.ServiceHandler({
				'url': core.env.aircraftService + 'GetComparisonData',
				'data': '{"aircraftId":"' + id + '"}',
				'dataType': 'html'
			});

			ServiceHandler.bind('loaded', function (event) {
				var data = ServiceHandler.data;
				model = $('div.specs-column', $('div#compare_models-column-model')).clone();
				$('div.specs-aircraft-data', model).append(data);
				$(model).attr({'id': 'comparison-' + aircraft.id});
				
				$('div.columnbrand', model).html(aircraft.brand);
				$('div.columnmodel', model).html(aircraft.model);
				$('img.aircraftimage', model).attr('src', '/assets/images/global/common/tools/aircraft/'+aircraft.id+'.png');
				$('a', $('div.specs-column-remove', model)).click(function(event) {
					event.preventDefault();
					ControlPanel.unselectAircraftById(aircraft.id);
				});

				$('div.specs-column').removeClass('last-child');
				
				$('div#specs-container').append(model);
				
				$('div.specs-column:last-child').addClass('last-child');
				
				$('div#comparison-conditions').css({'display': 'block'});
				ViewHandler.setMeasurement();
				
			});

		} else {
			maxAircraftSelected = true;
			ControlPanel.trigger('maxAircraftSelected', [selectedAircraft]);
		}

	}

	ControlPanel.unselectAircraftById = function (id) {
		var i,
			selected = [];

		for(i = 0; i < selectedAircraft.length; i = i + 1) {
			if(selectedAircraft[i].id === id) {
				$('#select-toggle-' + id + ' .toggle').css({'backgroundColor': 'transparent'});
				$('#group-item-' + id + ' .payload').hide('fast');
				$('#group-item-' + id + ' .payload').removeClass('selected');
				
				$('li#legend-' + selectedAircraft[i].id, $('ul#aircraftlegend')).remove();
				$('div#comparison-' + selectedAircraft[i].id, $('div#specs-container')).remove();

				selectedAircraft[i].selected = false;
				selectedAircraft.splice(i, 1);
				ControlPanel.trigger('aircraftUnselected', [selectedAircraft, aircraft]);

				if(selectedAircraft.length < options.maxAircraftSelected) {
					maxAircraftSelected = false;
				}

			}

		}

		$('div.specs-column').removeClass('last-child');
		if (selectedAircraft.length < 1) {
			$('div#comparison-conditions').css({'display': 'none'});
			$('div#specs-background').css({'display': 'block'});
		}
		

		//for (i = 0; i < selectedAircraft.length; i = i + 1) {
		//	selected.push(selectedAircraft[i].id);
		//}

		//core.ui.tools.State.aircraft= selected;
		core.ui.tools.updateHashAircraft();
	}
	
	ControlPanel.getAvailableColor = function () {
		var color = '#000';
		var colorOptions = ['#1c8099','#c29d57','#bfbfbf'];
		var c, i;
		
		for (c = 0; c < colorOptions.length; c = c + 1) {
			var inUse = false;
			for (i = 0; i < selectedAircraft.length; i = i + 1) {
				if (selectedAircraft[i].selectedColor === colorOptions[c]) {
					inUse = true;
				}
			}
			if (inUse == false) {
				color = colorOptions[c];
				break;
			}
		}
		return color;
	}
	
	ControlPanel.getFormattedRange = function (range) {
		x1 = range.toFixed(0) + '';
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(x1)) {
			x1 = x1.replace(rgx, '$1' + ',' + '$2');
		}
		return x1;
	}
	
	ControlPanel.updateLegendPayload = function (changedAircraft) {							
		var rangeNM, rangeKM, rangeMI;
		rangeNM = ControlPanel.getFormattedRange(changedAircraft.getRangeNM());
		rangeKM = ControlPanel.getFormattedRange(changedAircraft.getRangeKM());
		rangeMI = ControlPanel.getFormattedRange(changedAircraft.getRangeMI());
		
		$('div.legendrange', $('li#legend-'+changedAircraft.id)).html(rangeNM + 'nm = ' + rangeKM + 'km = ' + rangeMI + 'mi');
		$('div.legendpayload', $('li#legend-'+changedAircraft.id)).html(changedAircraft.pilots + ' crew + ' + changedAircraft.selectedPassengers + ' passengers ' + changedAircraft.reservefuel);
	}

	return initialize(data);
}

core.ui.tools.GoogleMapsSearchBox = function ($form, options) {
	var GoogleMapsSearchBox = $(this),
		location,
		defaultOptions = {
			'defaultLocation': new GLatLng(0, 0)
		};

	options = $.extend(true, {}, defaultOptions, options);
	


	GoogleMapsSearchBox.setLocation = function (GLatLong) {
		location = GLatLong;
		GoogleMapsSearchBox.trigger('locationChange');
	}

	GoogleMapsSearchBox.getLocation = function() {
		if(location) {
			return location;
		} else {
			return options.defaultLocation;
		}
	}
	
	GoogleMapsSearchBox.setLocationName = function (locationName) {
		$('#locationtitle').html(locationName);
	}
	
	GoogleMapsSearchBox.queryLocation = function (loc, country, tld) {
		var geocoder = new GClientGeocoder();
		var locquery = loc + ', ' + country;
		geocoder.setBaseCountryCode(tld);
		geocoder.getLocations(locquery, function(response) {
			if (!response || response.Status.code != 200 || response.Placemark.length < 1) {
				alert('no results found');
			} else if (response.Placemark.length == 1) {
				var place = response.Placemark[0];
				GoogleMapsSearchBox.setLocation(new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]));
				GoogleMapsSearchBox.setLocationName(place.address);
			} else {
				$('div#search-form').slideUp(function() {
					$('#search-results').html('<ul id="resultList"></ul>');
					for (var p=0;p<response.Placemark.length;p = p + 1) {
						var place = response.Placemark[p];
						
						$("#resultList").append('<li><a href=\"#\">'+place.address+'</a></li>');

						$('li', $("#resultList")).eq(p).unbind('click').bind('click', {'place':place}, function (event, place) {
							var place = event.data.place;
							
							event.preventDefault();	
							
							GoogleMapsSearchBox.setLocation(new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]));
							GoogleMapsSearchBox.setLocationName(place.address);

							$('div#search-results').css({'display': 'none'});
							$('div#search-form').css({'display': 'block'});
					
						});
					}

					$('div#search-results').slideDown();
				});

			}
		});
	}
	
	$('input#loc').keydown(function(event) {
			var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode));
			if (keycode == 13) { // keycode for enter key
				// force the 'Enter Key' to call function, not submit form
				//if ($('input#loc').val() != '') {
					GoogleMapsSearchBox.queryLocation($('input#loc').val(), $('select#country option:selected').text(), $('select#country').val());
				//}
				return false;
			} else  {
				return true;
			}
	});
	
	$('#searchbtnwrapper button.search_button').click(function(event) {
		event.preventDefault();
		//if ($('input#loc').val() != '') {
			GoogleMapsSearchBox.queryLocation($('input#loc').val(), $('select#country option:selected').text(), $('select#country').val());
		//}
	});

	//GoogleMapsSearchBox.setLocation(new GLatLng(37.686980, -97.335579));
	//GoogleMapsSearchBox.setLocationName('Wichita, KS');
	$('input#loc').val('Wichita, KS');
	GoogleMapsSearchBox.queryLocation('Wichita, KS', 'United States', 'US');
	
	return GoogleMapsSearchBox;

}

core.ui.tools.State = (function () {
	var State = {};

	if(core.env.getHash('view', window.location.hash)) {
		State.view = core.env.getHash('view', window.location.hash);
	} else if (State.view){
		
	} else {
		State.view = null;
	}

	if (core.env.getHash('aircraft', window.location.hash)) {
		State.aircraft = core.env.getHash('aircraft', window.location.hash).split('|');
	} else if(State.aircraft) {
		
	} else {
		State.aircraft = [];
	}
	
	return State;

}());

core.ui.tools.updateHashView = function () {
	var currentAircraft = core.env.getHash('aircraft', window.location.hash);
	if (currentAircraft) {
		window.location.hash = 'view=' + core.ui.tools.State.view + '&aircraft=' + currentAircraft;
	} else if (core.ui.tools.State.view) {
		window.location.hash = 'view=' + core.ui.tools.State.view;
	}
}

core.ui.tools.updateHashAircraft = function () {
	var selected = MapControlPanel.getSelectedAircraft(),
		aircraftIds = [];
	
	for (var i in selected) {
		aircraftIds.push(selected[i].id);
	}
	if (!core.ui.tools.State.view) {
		core.ui.tools.State.view = 'map';		
	}

	window.location.hash = 'view=' + core.ui.tools.State.view + '&aircraft=' + aircraftIds.join('|');
}

window.ViewHandler = core.ui.tools.ViewHandler({ 'state': 'map' });

//Sales Rep Functions added by Jennifer Pierson
function SelectLocation(loc) {
    //alert('me');

    __doPostBack('ctl00_ctl00_maincontent_maincontent_ctl00_UpdatePanelCountry', loc)
    $('div#salesrep-map').css({ 'display': 'none' });
    $('div#salesrep-model').css({ 'display': 'block' });
    $('div#salesrep-results').css({ 'display': 'none' });

//    switch (loc) {
//        case 'AF':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_1_africa_small.gif";
//            break;
//        case 'AS':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_2_asia_small.gif";
//            break;
//        case 'CA':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_3_central_america_mexico_small.gif";
//            break;
//        case 'EU':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_4_europe_small.gif";
//            break;
//        case 'ME':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_5_middle_east_small.gif";
//            break;
//        case 'NA':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_6_north_america_small.gif";
//            break;
//        case 'OC':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_7_oceania_pacific_islands_small.gif";
//            break;
//        case 'SA':
//            document.small_world.src = "/assets/images/global/common/tools/maps/map_8_south_america_small.gif";
//            break;
//    }

}
function ShowMap() {
    //alert('me');
    $('div#salesrep-map').css({ 'display': 'block' });
    $('div#salesrep-model').css({ 'display': 'none' });
    $('div#salesrep-results').css({ 'display': 'none' });
    //return false;
}

function BackToLocation(loc) {
    //alert('me');

    //__doPostBack('ctl00_ctl00_maincontent_maincontent_ctl00_UpdatePanelCountry', loc)
    $('div#salesrep-map').css({ 'display': 'none' });
    $('div#salesrep-model').css({ 'display': 'block' });
    $('div#salesrep-results').css({ 'display': 'none' });

    //return false;

}
function ShowHighlighting(loc) {
    //switch image in imagemap to highlight selected country
    switch (loc) {
        case 'AF':
            document.world.src="/assets/images/global/common/tools/maps/map_1_africa.gif";
            break;
        case 'AS':
            document.world.src = "/assets/images/global/common/tools/maps/map_2_asia.gif";
            break;
        case 'CA':
            document.world.src = "/assets/images/global/common/tools/maps/map_3_central_america_mexico.gif";
            break;
        case 'EU':
            document.world.src = "/assets/images/global/common/tools/maps/map_4_europe.gif";
            break;
        case 'ME':
            document.world.src = "/assets/images/global/common/tools/maps/map_5_middle_east.gif";
            break;
        case 'NA':
            document.world.src = "/assets/images/global/common/tools/maps/map_6_north_america.gif";
            break;
        case 'OC':
            document.world.src = "/assets/images/global/common/tools/maps/map_7_oceania_pacific_islands.gif";
            break;
        case 'SA':
            document.world.src = "/assets/images/global/common/tools/maps/map_8_south_america.gif";
            break;      
    }
}
function HideHighlighting() {
    //switch image in imagemap to plain image with no highlighting
    document.world.src = "/assets/images/global/common/tools/maps/map_0_plain.gif";
}


