 /**
 * Google Maps API v3 - JavaScript Functions
 * 
 * @license     ALL RIGHTS RESERVED
 *
 * @author      Trevor Kensiski
 * @email       trevor@gutensite.com
 * @author      Brett Fowle
 * @email       brett@gutensite.com
 *
 * @link        http://gutensite.com
 * 
 * @file        google_map.3.1.js
 * @version     3.1
 * @date        07/23/2010
 * 
 * Copyright (c) 2010 GutenSite
 *
 *********************************************************************************
 *    _____  ____   ____   _____ _      ______   __  __          _____   _____ 
 *   / ____|/ __ \ / __ \ / ____| |    |  ____| |  \/  |   /\   |  __ \ / ____|
 *  | |  __| |  | | |  | | |  __| |    | |__    | \  / |  /  \  | |__) | (___  
 *  | | |_ | |  | | |  | | | |_ | |    |  __|   | |\/| | / /\ \ |  ___/ \___ \ 
 *  | |__| | |__| | |__| | |__| | |____| |____  | |  | |/ ____ \| |     ____) |
 *   \_____|\____/ \____/ \_____|______|______| |_|  |_/_/    \_\_|    |_____/ 
 *
 *********************************************************************************
 * This class was made to simplify creating complex maps with the Google API v3
 * It has a counter that prevent colisions when creating multiple maps on the same page.
 * All you have to do is initialize the map and set some default values and turn on
 * the features you want and in the HTML put a container div where you want the map to
 * show up. The class does the rest.
 *
 *	CLASS HIERARCHY:
 *  ================
 *
 *	[Google_map]
 *   |
 *   |-> init()
 *   |-> init_map()
 *   |-> set_values()
 *   |-> set_controls()
 *   |-> set_views()
 *   |-> build_containers()
 *   |-> set_customUI()
 *   |-> zoom_controls()
 *   |-> view_controls()
 *   |-> toggle_button()
 *   |-> toggle_map_view()
 *   |-> toggle_street_view()
 *   |-> toggle_directions()
 *   |-> _map_to_directions()
 *   |-> _directions_to_map()
 *   |-> _directions_to_street()
 *   |-> _map_to_street()
 *   |-> _street_to_map()
 *   |-> _street_to_directions()
 *   |-> _resize_center_map()
 *   |-> print_map()
 *   |-> check_states()
 *   |-> init_street()
 *   |-> process_street_view()
 *   |-> street_view_error()
 *   |-> init_directions()
 *   |-> do_directions()
 *   |-> directions_error()
 *   |-> create_direction_marker()
 *   |-> clear_map()
 *   |
 *   '
 */

var google_map_counter = 0;
var map = new Array();

var Google_map = new Class({

	/**
	* Options
	*/
	options: {
		counter     : 0,
		starting_mode : 'map',
		elements: {
			containers: {
				main             : 'map_container',
				controls         : 'map_controls',
				map              : 'map_canvas',
				street           : 'map_street',
				directions       : 'map_directions',
				directions_input : 'map_directions_input',
				directions_panel : 'map_directions_panel'
			},
			inputs: {
				start_address          : 'start_address',
				end_address            : 'end_address',
				side_bar_start_address : 'side_bar_start_address' // This is used for the side bar in the MLS
			},
			buttons: {
				zoom              : 'b_zoom',
				street_view       : 'b_street_view',
				map               : 'b_map',
				terrain           : 'b_terrain',
				satellite         : 'b_satellite',
				get_directions    : 'b_get_directions',
				toggle_directions : 'directions',
				toggle_street     : 'street_view',
				toggle_map        : 'map_view',
				toggle_print      : 'print' 
			},
			other: {
				vertical_divider   : 'vertical_divider',
				horizontal_divider : 'horizontal_divider',
				default_icon       : null,
				start_icon         : null
			},
			toggles: {
				controls: {},
				map: {}
			}
		},
		map: {
			construct: null,
			markers: {
				raw_data: {}, // The raw data to turn into points
				points: [],
				info_windows: [],
				current_info_window: null,
				icons: {
					default_icon: null
				}
			},
			controls: {
				customUI               : false,
				draggable              : true,
				scrollwheel            : true,
				disableDoubleClickZoom : false,
				disableDefaultUI       : false,
				zoomControl            : false,
				scaleControl           : false,
				streetView             : false,
				custom_streetView      : false, // This is set if streetView is true and customUI is true
				keyboardShortcuts      : true,
				views: {
					map       : true,
					satellite : false,
					terrain   : false,
					hybrid    : true // Turns satellite mode into HYBRID satellite mode
				}
			},
			settings: {
				zoom : 8,
				default_view : 'SATELLITE',
				position: {
					center : null, // The lat/lng that google creates use for most position based things
					lat    : null, // The lat to set as the map center
					lng    : null // The lng to set as the map center
				}
			},
			bounds: null,
			types: {}
		},
		directions: {
			status   : true, // are directions turned on
			service  : null,
			renderer : null,
			travel_type: {},
			polyline : null,
			markers  : []
		},
		street_view: {
			status   : true, // is street view turned on
			panorama : null,
			service  : null
		},
		geocoder: {
			construct: null
		},
		morph: {}
	},
	
	/**
	 * Intialize the class
	 */
	init: function(settings) {		
		// Initialize the map
		this.init_map(settings);
		
		if (settings.streetView)
		{
			// initialize Street View
			this.init_street(settings);
		}
		if (settings.directions)
		{	
			// Initialize Driving Directions
			this.init_directions(settings);
		}
	},

	
	/**
	 * Init Map
	 */
	init_map: function(settings) {
		// Set the counter so we can refrence everything with a unique ID
		if (this.options.counter == 0)
		{
			google_map_counter++;
			this.options.counter = google_map_counter;
		}
		
		// Set the lat lng and generate the "center"
		this.set_values(settings);
		
		// Setup the controls for the map
		this.set_controls(settings);
		
		// Setup the views for the map
		this.set_views(settings);
		
		// Build the containers
		this.build_containers(settings);
		
		this.options.map.construct = new google.maps.Map($(this.options.elements.containers.map + '_' + this.options.counter), {
			zoom                   : this.options.map.settings.zoom,
			center                 : this.options.map.settings.position.center,
			mapTypeId              : this.options.map.types[this.options.map.settings.default_view],
			disableDoubleClickZoom : this.options.map.controls.disableDoubleClickZoom,
			disableDefaultUI       : this.options.map.controls.disableDefaultUI,
			scaleControl           : this.options.map.controls.scaleControl,
			scrollwheel            : this.options.map.controls.scrollwheel,
			draggable              : this.options.map.controls.draggable
		});
		
		this.options.map.bounds = new google.maps.LatLngBounds(this.options.map.settings.position.center);
		
		if (this.options.map.controls.customUI)
		{
			this.set_customUI();
		}
		
		if (this.options.map.markers.raw_data.length > 0)
		{
			google.maps.event.addListener(this.options.map.construct, 'click', function() {
				if (this.options.map.markers.current_info_window)
					this.options.map.markers.current_info_window.close();
			}.bind(this));
			
			this.create_markers();
		
			if (this.options.map.markers.points.length > 2)
				this.options.map.construct.fitBounds(this.options.map.bounds);
		}
	},
	
	/**
	 * Set Center
	 */
	set_values: function(settings) {
		if ($defined(settings.lat))
			this.options.map.settings.position.lat = settings.lat;
			
		if ($defined(settings.lng))
			this.options.map.settings.position.lng = settings.lng;
		
		// We can setup the center since we have default
		this.options.map.settings.position.center = new google.maps.LatLng(this.options.map.settings.position.lat, this.options.map.settings.position.lng);
		
		if ($defined(settings.zoom) && $type(settings.zoom) == 'number')
			this.options.map.settings.zoom = settings.zoom;
			
		if ($defined(settings.markers))
			this.options.map.markers.raw_data = settings.markers;
			
		if ($defined(settings.elements.default_icon))
		{
			this.options.elements.other.default_icon = settings.elements.default_icon;
		}
	},
	
	set_controls: function(settings) {
		if ($defined(settings.controls.disableDoubleClickZoom) && $type(settings.controls.disableDoubleClickZoom) == 'boolean')
		{
			this.options.map.controls.disableDoubleClickZoom = settings.controls.disableDoubleClickZoom;
		}
		
		if ($defined(settings.controls.disableDefaultUI) && $type(settings.controls.disableDefaultUI) == 'boolean')
		{
			this.options.map.controls.disableDefaultUI = settings.controls.disableDefaultUI;
		}
		
		if ($defined(settings.controls.scaleControl) && $type(settings.controls.scaleControl) == 'boolean')
		{
			this.options.map.controls.scaleControl = settings.controls.scaleControl;
		}
		
		if ($defined(settings.controls.scrollwheel) && $type(settings.controls.scrollwheel) == 'boolean')
		{
			this.options.map.controls.scrollwheel = settings.controls.scrollwheel;
		}
		
		if ($defined(settings.controls.draggable) && $type(settings.controls.draggable) == 'boolean')
		{
			this.options.map.controls.draggable = settings.controls.draggable;
		}
		
		if ($defined(settings.controls.streetView) && $type(settings.controls.streetView) == 'boolean')
		{
			this.options.map.controls.streetView = settings.controls.streetView;
		}
		
		if ($defined(settings.controls.zoomControl) && $type(settings.controls.zoomControl) == 'boolean')
		{
			this.options.map.controls.zoomControl = settings.controls.zoomControl;
		}
		
		if ($defined(settings.controls.customUI) && $type(settings.controls.customUI) == 'boolean')
		{
			this.options.map.controls.customUI = settings.controls.customUI;
			
			if (this.options.map.controls.customUI)
			{
				this.options.map.controls.disableDefaultUI = true;
				
				if (this.options.map.controls.streetView)
				{
					this.options.map.controls.streetView = false;
					this.options.map.controls.custom_streetView = true;
				}
			}
		}
	},
	
	set_views: function(settings)
	{
		// Turn on the map view modes
		if ($defined(settings.views.map) && $type(settings.views.map) == 'boolean')
		{
			this.options.map.controls.views.map = settings.views.map;
		}
		if ($defined(settings.views.satellite) && $type(settings.views.satellite) == 'boolean')
		{
			this.options.map.controls.views.satellite = settings.views.satellite;
		}
		if ($defined(settings.views.terrain) && $type(settings.views.terrain) == 'boolean')
		{
			this.options.map.controls.views.terrain = settings.views.terrain;
		}
		if ($defined(settings.views.hybrid) && $type(settings.views.hybrid) == 'boolean')
		{
			this.options.map.controls.views.hybrid = settings.views.hybrid;
		}
		
		// Set the default view type
		if ($defined(settings.views.default_view) && (settings.views.default_view == 'ROADMAP' || settings.views.default_view == 'SATELLITE' || settings.views.default_view == 'TERRAIN'))
		{
			this.options.map.settings.default_view = settings.views.default_view.toUpperCase();
			this.options.map.controls.views[settings.views.default_view.toLowerCase()] = true;
		}
		
		// Set the default map mode
		if ($defined(settings.starting_mode))
		{
			this.options.starting_mode = settings.starting_mode;
		}
		
		// the diffrent types of maps
		if (this.options.map.controls.views.hybrid)
		{
			this.options.map.types.SATELLITE = google.maps.MapTypeId.HYBRID;
		}
		else
		{
			this.options.map.types.SATELLITE = google.maps.MapTypeId.SATELLITE;
		}
		
		this.options.map.types.TERRAIN = google.maps.MapTypeId.TERRAIN;
		this.options.map.types.ROADMAP = google.maps.MapTypeId.ROADMAP;
	},
	
	build_containers: function (settings) {
		// Set the containers here
		if ($defined(settings.elements.container))
		{
			this.options.elements.containers.main = settings.elements.container;
		}
		if ($defined(settings.elements.controls))
		{
			this.options.elements.containers.controls = settings.elements.controls;
		}
		if ($defined(settings.elements.map))
		{
			this.options.elements.containers.map = settings.elements.map;
		}
		if ($defined(settings.elements.street_view))
		{
			this.options.elements.containers.street_view = settings.elements.street_view;
		}
		if ($defined(settings.elements.directions))
		{
			this.options.elements.containers.directions = settings.elements.directions;
		}
	
		// Now create the containers
		var containers = $(this.options.elements.containers.main);
	
		if (this.options.street_view.status || this.options.directions.status)
		{
			var controls_container = new Element('div', {
				'id'    : this.options.elements.containers.controls + '_' + this.options.counter,
				'class' : this.options.elements.containers.controls
			});
			
			var controls_ul = new Element('ul');
			
			if (this.options.directions.status)
			{
				var directions = new Element('li', {
					'id' : 'toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.counter,
					'class' : this.options.elements.buttons.toggle_directions + ' off f_left',
				    'events' : {
				    	'click' : function() {
			        		this.toggle_button('controls', 'directions', 'click');
				    		this.toggle_directions();
				    	}.bind(this),
				        'mouseenter' : function() {
			        		this.toggle_button('controls', 'directions');
				        }.bind(this),
				        'mouseleave' : function() {
			        		this.toggle_button('controls', 'directions');
				        }.bind(this)
				    }
				});
				
				// Divider
				var directions_divider = new Element('li', {
					'class' : this.options.elements.other.vertical_divider + ' f_left'
				});
				
				var directions_print = new Element('li', {
					'id' : 'toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter,
					'class' : this.options.elements.buttons.toggle_print + ' off f_left',
					'style' : 'display: none',
				    'events' : {
				    	'click' : function() {
				    		this.print_map();
				    	}.bind(this),
				        'mouseenter' : function() {
				        	$('toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter).addClass('on');
				        }.bind(this),
				        'mouseleave' : function() {
				        	$('toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter).removeClass('on');
				        }.bind(this)
				    }
				});
				
				directions.inject(controls_ul);
				directions_divider.inject(controls_ul);
				directions_print.inject(controls_ul);
			}
			
			// Map View
			var map_view = new Element('li', {
				'id' : 'toggle_' + this.options.elements.buttons.toggle_map + '_' + this.options.counter,
				'class' : this.options.elements.buttons.toggle_map + ' off f_right',
			    'events' : {
			    	'click' : function() {
			        	this.toggle_button('controls', 'map', 'click');
				    	this.toggle_map_view();
			    	}.bind(this),
			        'mouseenter' : function() {
			        	this.toggle_button('controls', 'map');
			        }.bind(this),
			        'mouseleave' : function() {
			        	this.toggle_button('controls', 'map');
			        }.bind(this)
			    }
			});
			map_view.inject(controls_ul);
			
			// Street View
			if (this.options.street_view.status)
			{
				// Divider
				var street_divider = new Element('li', {
					'class' : 'vertical_divider f_right'
				});
			
				var street_view = new Element('li', {
					'id' : 'toggle_' + this.options.elements.buttons.toggle_street + '_' + this.options.counter,
					'class' : this.options.elements.buttons.toggle_street + ' off f_right',
				    'events' : {
				    	'click' : function() {
			        		this.toggle_button('controls', 'street', 'click');
				    		this.toggle_street_view();
				    	}.bind(this),
				        'mouseenter' : function() {
			        		this.toggle_button('controls', 'street');
				        }.bind(this),
				        'mouseleave' : function() {
			        		this.toggle_button('controls', 'street');
				        }.bind(this)
				    }
				});
				
				street_divider.inject(controls_ul);
				street_view.inject(controls_ul);
			}
			controls_ul.inject(controls_container);
			
			// Clear the controls
			var clear_floats = new Element('div', {
				'class' : 'horizontal_divider'
			});
			
			clear_floats.inject(controls_container);
			controls_container.inject(containers);
			
		}
		
		var c_map = new Element('div', {
			'id' : this.options.elements.containers.map + '_' + this.options.counter,
			'class' : this.options.elements.containers.map
		});
		c_map.inject(containers);
		
		if (this.options.street_view.status)
		{
			var c_street = new Element('div', {
				'id' : this.options.elements.containers.street + '_' + this.options.counter,
				'class' : this.options.elements.containers.street
			});
			c_street.inject(containers);
			
			if (typeof this.options.morph.street == "undefined")
			{
				this.options.morph.street = new Fx.Morph(this.options.elements.containers.street+'_'+this.options.counter, {
					duration: 500,
					link: 'cancel'
				});
			}
		}
		
		if (this.options.directions.status)
		{
			var c_direction = new Element('div', {
				'id' : this.options.elements.containers.directions + '_' + this.options.counter,
				'class' : this.options.elements.containers.directions
			});
			
			/*****************************
			 * Create this block of code *
			 *****************************
				<div class="direction_inputs">
					<label for="start_address_{counter}">Start Address</label><br />
					<input type="text" name="start_address_{counter}" value="" /><br />
					<label for="end_address_{counter}">End Address</label><br />
					<input type="text" name="start_address_{counter}" value="" /><br />
					<div id="get_directions_{counter}" class="b_get_directions off"></div>
				</div>
			*/
			var direction_inputs = new Element('div', {
				'id'   : this.options.elements.containers.directions_input + '_' + this.options.counter,
				'class': this.options.elements.containers.directions_input
			});
			direction_inputs.appendChild(new Element('label', {
				'for' :this.options.elements.inputs.start_address + '_' + this.options.counter,
				'html':'Start Address'
			}));
			direction_inputs.appendChild(new Element('br'));
			direction_inputs.appendChild(new Element('input', {
				'id'  :this.options.elements.inputs.start_address + '_' + this.options.counter,
				'name':this.options.elements.inputs.start_address + '_' + this.options.counter,
				'type':'text'
			}));
			direction_inputs.appendChild(new Element('br'));
			direction_inputs.appendChild(new Element('label', {
				'for' :this.options.elements.inputs.end_address + '_' + this.options.counter,
				'html':'Destination'
			}));
			direction_inputs.appendChild(new Element('br'));
			direction_inputs.appendChild(new Element('input', {
				'id'  :this.options.elements.inputs.end_address + '_' + this.options.counter,
				'name':this.options.elements.inputs.end_address + '_' + this.options.counter,
				'type':'text'
			}));
			direction_inputs.appendChild(new Element('br'));
			direction_inputs.appendChild(new Element('div', {
				'id'   :this.options.elements.buttons.get_directions + '_' + this.options.counter,
				'class': this.options.elements.buttons.get_directions + ' off'
			}));
			
			direction_inputs.inject(c_direction);
			
			var direction_panel = new Element('div', {
				'id': this.options.elements.containers.directions_panel + '_' + this.options.counter,
				'class': this.options.elements.containers.directions_panel
			});
			
			direction_panel.inject(c_direction);
			c_direction.inject(containers);
			
			$(this.options.elements.buttons.get_directions + '_' + this.options.counter).addEvent('click', function() {
				this.do_directions();
			}.bind(this)).addEvent('mouseenter', function() {
				$(this.options.elements.buttons.get_directions + '_' + this.options.counter).addClass('on');
			}.bind(this)).addEvent('mouseleave', function() {
				$(this.options.elements.buttons.get_directions + '_' + this.options.counter).removeClass('on');
			}.bind(this));
				
			if (typeof this.options.morph.directions == "undefined")
			{
				this.options.morph.directions = new Fx.Morph(this.options.elements.containers.directions+'_'+this.options.counter, {
					duration: 500,
					link: 'cancel'
				});
			}
		}
		
		if (typeof this.options.morph.map == "undefined")
		{
			this.options.morph.map = new Fx.Morph(this.options.elements.containers.map+'_'+this.options.counter, {
				duration: 500,
				link: 'cancel'
			});
		}
		
		var note = new Element('div', {
			'id'   : 'map_note_' + this.options.counter,
			'class': 'map_note',
			'html' : 'Note: the precise location may not always be accurately displayed on the map, due to sometimes inaccurate geocoding.'
		});
		
		note.inject(containers);
		
		
		this.options.elements.toggles.controls.map = $('toggle_' + this.options.elements.buttons.toggle_map + '_' + this.options.counter);
		if (this.options.starting_mode == "map")
		{
			this.toggle_button('controls', 'map', 'click');
			this.options.elements.toggles.controls.active = 'map';
		}
		
		if (this.options.street_view.status)
		{
			this.options.elements.toggles.controls.street = $('toggle_' + this.options.elements.buttons.toggle_street + '_' + this.options.counter);
			
			if (this.options.starting_mode == "street")
			{
				this.toggle_button('controls', 'street', 'click');
				this._map_to_street();
				this.options.elements.toggles.controls.active = 'street';
			}
		}
		
		if (this.options.directions.status)
		{
			this.options.elements.toggles.controls.directions = $('toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.counter);
			
			if (this.options.starting_mode == "directions")
			{
				this.toggle_button('controls', 'directions', 'click');
				this._map_to_directions();
				this.options.elements.toggles.controls.active = 'directions';
			}
		}
	},
	
	set_customUI: function() {
		if (this.options.map.controls.zoomControl || this.options.map.controls.custom_streetView)
		{
			this.zoom_controls();
		}
	
		if (this.options.map.controls.views.map || this.options.map.controls.views.terrain || this.options.map.controls.views.satellite)
		{
			this.view_controls();
		}
	},
	
	zoom_controls: function() {
		var container = new Element('div');
		
		if (this.options.map.controls.zoomControl)
		{
			var zoom = new Element('div');
				zoom.setStyle('padding', '5px 0px 0px 5px');
				
			var zoom_in = new Element('div', {
				'id' : this.options.elements.buttons.zoom + '_in_' + this.options.counter,
			    'class' : this.options.elements.buttons.zoom + ' in off',
			    'events' : {
			    	'click' : function() {
			    		this.options.map.construct.setZoom(this.options.map.construct.getZoom() + 1);
			    	}.bind(this),
			        'mouseenter' : function() {
			        	$(this.options.elements.buttons.zoom + '_in_' + this.options.counter).addClass('on');
			        }.bind(this),
			        'mouseleave' : function() {
			        	$(this.options.elements.buttons.zoom + '_in_' + this.options.counter).removeClass('on');
			        }.bind(this)
			    }
			});
			
			zoom_in.inject(zoom);
			
			var zoom_out = new Element('div', {
				'id' : this.options.elements.buttons.zoom + '_out_' + this.options.counter,
			    'class' : this.options.elements.buttons.zoom + ' out off',
			    'events' : {
			    	'click' : function() {
			    		this.options.map.construct.setZoom(this.options.map.construct.getZoom() - 1);
			    	}.bind(this),
			        'mouseenter' : function() {
			        	$(this.options.elements.buttons.zoom + '_out_' + this.options.counter).addClass('on');
			        }.bind(this),
			        'mouseleave' : function() {
			        	$(this.options.elements.buttons.zoom + '_out_' + this.options.counter).removeClass('on');
			        }.bind(this)
			    }
			});
		
			zoom_out.inject(zoom);
			zoom.inject(container);
		}
		
		if (this.options.map.controls.custom_streetView)
		{
			var street = new Element('div');
				street.setStyle('padding', '5px 0px 0px 5px');
			
			var street_view = new Element('div', {
				'id' : this.options.elements.buttons.street_view + '_' + this.options.counter,
			    'class' : this.options.elements.buttons.street_view + ' off',
			    'events' : {
			    	'click' : function() {
						this.toggle_street_view();
			        	this.toggle_button('controls', 'street', 'click');
			    	}.bind(this),
			        'mouseenter' : function() {
			        	$(this.options.elements.buttons.street_view + '_' + this.options.counter).addClass('on');
			        }.bind(this),
			        'mouseleave' : function() {
			        	$(this.options.elements.buttons.street_view + '_' + this.options.counter).removeClass('on');
			        }.bind(this)
			    }
			});
			
			street_view.inject(street)
		
			street.inject(container)
		}
		
		this.options.map.construct.controls[google.maps.ControlPosition.TOP_LEFT].push(container);
	},
	
	view_controls: function() {
		// Make sure we have more than one button to use
		if (this.options.map.controls.views.map && (this.options.map.controls.views.satellite || this.options.map.controls.views.terrain))
		{
			var container = new Element('div');
				container.setStyle('padding', '5px');
			
			// We always show the map one since its the "default"
			var map_view = new Element('div', {
				'id' :  this.options.elements.buttons.map + '_' + this.options.counter,
			    'class' : 'map_toggle ' + this.options.elements.buttons.map + ' off',
			    'events' : {
			    	'click' : function() {
			    		this.options.map.construct.setMapTypeId(this.options.map.types.ROADMAP);
			        	this.toggle_button('map', 'map', 'click');
			    	}.bind(this),
			        'mouseenter' : function() {
			        	this.toggle_button('map', 'map');
			        }.bind(this),
			        'mouseleave' : function() {
			        	this.toggle_button('map', 'map');
			        }.bind(this)
			    }
			});
			
			container.appendChild(map_view);			
			
			var terrain_view;
			
			// We have 2 versions of the satellite button since it can either be the end or not
			// so lets find out which one to use
			if (this.options.map.controls.views.satellite && !this.options.map.controls.views.terrain)
			{
				var satellite_view = new Element('div', {
					'id' : this.options.elements.buttons.satellite + '_' + this.options.counter,
				    'class' : 'map_toggle ' + this.options.elements.buttons.satellite + ' off',
				    'events' : {
				    	'click' : function() {
				    		this.options.map.construct.setMapTypeId(this.options.map.types.SATELLITE);
			        		this.toggle_button('map', 'satellite', 'click');
				    	}.bind(this),
				        'mouseenter' : function() {
			        		this.toggle_button('map', 'satellite');
				        }.bind(this),
				        'mouseleave' : function() {
			        		this.toggle_button('map', 'satellite');
				        }.bind(this)
				    }
				});
				
				container.appendChild(satellite_view);
			}
			else
			{
				// Guess we are not using it as the end so lets make sure its set and then print out the last one.
				if (this.options.map.controls.views.satellite)
				{
					var satellite_view = new Element('div', {
						'id' : this.options.elements.buttons.satellite + '_' + this.options.counter,
					    'class' : 'map_toggle ' + this.options.elements.buttons.satellite + ' off',
					    'events' : {
					    	'click' : function() {
					    		this.options.map.construct.setMapTypeId(this.options.map.types.SATELLITE);
				        		this.toggle_button('map', 'satellite', 'click');
					    	}.bind(this),
					        'mouseenter' : function() {
				        		this.toggle_button('map', 'satellite');
					        }.bind(this),
					        'mouseleave' : function() {
				        		this.toggle_button('map', 'satellite');
					        }.bind(this)
					    }
					});
					
					satellite_view.inject(container);
				}
							
				terrain_view = new Element('div', {
					'id' : this.options.elements.buttons.terrain + '_' + this.options.counter,
				    'class' : 'map_toggle ' + this.options.elements.buttons.terrain + ' off',
				    'events' : {
				    	'click' : function() {
			    			this.options.map.construct.setMapTypeId(this.options.map.types.TERRAIN);
				        	this.toggle_button('map', 'terrain', 'click');
				    	}.bind(this),
				        'mouseenter' : function() {
				        	this.toggle_button('map', 'terrain');
				        }.bind(this),
				        'mouseleave' : function() {
				        	this.toggle_button('map', 'terrain');
				        }.bind(this)
				    }
				});
				
				terrain_view.inject(container);
			}
			
			this.options.map.construct.controls[google.maps.ControlPosition.TOP_RIGHT].push(container);
			
			if (this.options.map.controls.views.map)
			{
				this.options.elements.toggles.map.map = map_view;		
				if (this.options.map.settings.default_view == "ROADMAP")
				{
					this.toggle_button('map', 'map', 'click');
					this.options.elements.toggles.map.active = 'map';
				}
			}
				
			if (this.options.map.controls.views.satellite)
			{
				this.options.elements.toggles.map.satellite = satellite_view
			
				if (this.options.map.settings.default_view == "SATELLITE")
				{
					this.toggle_button('map', 'satellite', 'click');
					this.options.elements.toggles.map.active = 'satellite';
				}
			}
			
			if (this.options.map.controls.views.terrain)
			{
				this.options.elements.toggles.map.terrain = terrain_view;
			
				if (this.options.map.settings.default_view == "TERRAIN")
				{
					this.toggle_button('map', 'terrain', 'click');
					this.options.elements.toggles.map.active = 'terrain';
				}
			}
		}

	},
	
	toggle_button: function(section, button, action) {		
		// Is this event a mouse over or a click event
		if (action == 'click')
		{
			if (this.options.elements.toggles[section].active != button)
			{
				// Set the button as active
				this.options.elements.toggles[section].active = button;
				
				for(var key in this.options.elements.toggles[section])
				{
					if (key != 'active')
					{
						if (this.options.elements.toggles[section].active == key)
						{
							this.options.elements.toggles[section][key].addClass('on');
						}
						else
						{
							this.options.elements.toggles[section][key].removeClass('on');
						}
					}
				}
			}
		}
		else
		{
			// Only do the toggle if the button is not active
			if (this.options.elements.toggles[section].active != button)
			{
				if (this.options.elements.toggles[section][button].hasClass('on'))
				{
					this.options.elements.toggles[section][button].removeClass('on');
				}
				else
				{
					this.options.elements.toggles[section][button].addClass('on');
				}
			}
		}
	},
	
	toggle_map_view: function() {
		if (this.check_states(false, true, false))
		{
			this._street_to_map();
		}
		
		if (this.check_states(true, false, true))
		{
			this._directions_to_map();
		}
	},

	toggle_street_view: function() {
		if (this.check_states(true, false, false))
		{
			this._map_to_street();
		}
		
		if (this.check_states(true, false, true))
		{
			this._directions_to_street();
		}
	},
	
	toggle_directions: function() {
		if (this.check_states(true, false, false))
		{
			this._map_to_directions();
		}
		
		if (this.check_states(false, true, false))
		{
			this._street_to_directions();
		}
	},
	
	_map_to_directions: function() {
		this.clear_map();
		// Find the width of the main container since the map cannot be bigger than that.
		container_width_before = parseInt($(this.options.elements.containers.main).getStyle('width')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-right')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-left'));
		
		// Now figure out how much we need to shrink it to fit the directions div (which is 238px for now)
		container_width_after  = parseInt(container_width_before) - 238;
		
		// Shrink the map and fade the directions in
		this.options.morph.map.set({'display':'block', 'width':container_width_before+'px', 'float':'right'}).start({'width':container_width_after+'px'}).chain(function() {
			this.options.morph.directions.set({'display':'block', 'opacity':0, 'width':'238px'}).start({'opacity':1}).chain(function () { this._resize_center_map(); }.bind(this));
		}.bind(this));
	},

	_directions_to_map: function() {
		this.clear_map();
		this.create_markers();
		// Find the width of the main container since the map cannot be bigger than that.
		container_width_before = parseInt($(this.options.elements.containers.main).getStyle('width')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-right')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-left'));
		
		// Now figure out where we are starting from when removing the directions div (which is 238px for now)
		container_width_after  = parseInt(container_width_before) - 238;
		
		// Fade the directions out, and enlarge the map Make sure we remove the maped route as well
		this.options.morph.directions.set({'display':'block', 'opacity':1, 'width':'238px'}).start({'opacity':0}).chain(function() {
			$(this.options.elements.containers.directions+'_'+this.options.counter).setStyle('display','none');
			this.options.morph.map.set({'display':'block', 'width':container_width_after+'px'}).start({'width':container_width_before+'px'}).chain(function () { this._resize_center_map(); }.bind(this));
		}.bind(this));
	},

	_directions_to_street: function() {
		this.clear_map();
		// Find the width of the main container since the map cannot be bigger than that.
		container_width_before = parseInt($(this.options.elements.containers.main).getStyle('width')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-right')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-left'));
		
		// Now figure out where we are starting from when removing the directions div (which is 238px for now)
		container_width_after  = parseInt(container_width_before) - 238;
		
		// Fade the directions out, and enlarge the map Make sure we remove the maped route as well
		this.options.morph.directions.set({'display':'block', 'opacity':1, 'width':'238px'}).start({'opacity':0}).chain(function() {
			$(this.options.elements.containers.directions+'_'+this.options.counter).setStyle('display','none');
			this.options.morph.map.set({'display':'block', 'width':container_width_after+'px'}).start({'width':container_width_before+'px'}).chain(function() {
				$(this.options.elements.containers.street + '_' + this.options.counter).setStyles({'opacity':0, 'display':'block'});
				
				this.options.street_view.service.getPanoramaByLocation(this.options.map.settings.position.center, 50, this.process_street_view.bind(this));
				/* STREET VIEW OLD
				this.options.street_view.panarama = new google.maps.StreetViewPanorama($(this.options.elements.containers.street + '_' + this.options.counter), {
					enableCloseButton: false,
					position: this.options.map.settings.position.center
				});
				*/
				this._resize_center_map();
				this.options.morph.map.set({'display':'block', 'opacity':1}).start({'opacity':0}).chain(function() {
					$(this.options.elements.containers.map+'_'+this.options.counter).setStyles({'opacity' : 0, 'display' : 'none'});
					
					// Now created the node by setting display to block and fade the street view in
					this.options.morph.street.set({'display':'block', 'position':'relative', 'left':0, 'opacity':0}).start({'opacity':1});
				}.bind(this));
			}.bind(this));
		}.bind(this));
	},

	_map_to_street: function() {	
		this.clear_map();	
		$(this.options.elements.containers.street + '_' + this.options.counter).setStyles({'opacity':0, 'display':'block'});
		
		this.options.street_view.service.getPanoramaByLocation(this.options.map.settings.position.center, 50, this.process_street_view.bind(this));
		/* STREET VIEW OLD
		this.options.street_view.panarama = new google.maps.StreetViewPanorama($(this.options.elements.containers.street + '_' + this.options.counter), {
			enableCloseButton: false,
			position: this.options.map.settings.position.center
		});
		*/
			
		this.options.morph.map.set({'display':'block', 'opacity':1}).start({'opacity':0}).chain(function() {
			$(this.options.elements.containers.map+'_'+this.options.counter).setStyles({'opacity' : 0, 'display' : 'none'});
			
			// Now created the node by setting display to block and fade the street view in
			this.options.morph.street.set({'display':'block', 'opacity':0}).start({'opacity':1});
		}.bind(this));
	},

	_street_to_map: function() {
		this.clear_map();
		this.create_markers();
		// Lets fade the street view out and "destroy" the node by setting display to none
		this.options.morph.street.set({'display':'block', 'opacity':1}).start({'opacity':0}).chain(function() {
			$(this.options.elements.containers.street + '_' + this.options.counter).setStyles({'opacity' : 0, 'display' : 'none'});
			
			// And then fade the map back in and "create" the node by setting display to block
			this.options.morph.map.set({'display':'block', 'opacity':0}).start({'opacity':1}).chain(function() {this._resize_center_map();}.bind(this));
		}.bind(this));
	},

	_street_to_directions: function() {
		this.clear_map();
		// Lets fade the street view out and "destroy" the node by setting display to none
		this.options.morph.street.set({'display':'block', 'opacity':1}).start({'opacity':0}).chain(function() {
			$(this.options.elements.containers.street + '_' + this.options.counter).setStyles({'opacity' : 0, 'display' : 'none'});
			
			// And then fade the map back in and "create" the node by setting display to block
			this.options.morph.map.set({'display':'block', 'opacity':0}).start({'opacity':1}).chain(function() {
				// Find the width of the main container since the map cannot be bigger than that.
				container_width_before = parseInt($(this.options.elements.containers.main).getStyle('width')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-right')) - parseInt($(this.options.elements.containers.map + '_' + this.options.counter).getStyle('border-left'));
				
				// Now figure out how much we need to shrink it to fit the directions div (which is 238px for now)
				container_width_after  = parseInt(container_width_before) - 238;
				
				// Shrink the map and fade the directions in
				this.options.morph.map.set({'display':'block', 'width':container_width_before+'px', 'float':'right'}).start({'width':container_width_after+'px'}).chain(function() {
					this.options.morph.directions.set({'display':'block', 'opacity':0, 'width':'238px'}).start({'opacity':1}).chain(function () { this._resize_center_map(); }.bind(this));
				}.bind(this));
			}.bind(this));
		}.bind(this));
	},

	/**
	 * Resize Center Map
	 * recenters the map after a resize of the view window
	 */
	_resize_center_map: function() {
		google.maps.event.trigger(this.options.map.construct, 'resize');
		this.options.map.construct.panTo(this.options.map.settings.position.center); 
	},
	
	print_map: function(start_address, end_address) {
		var url = 'http://maps.google.com/maps?saddr=' + start_address + '&daddr=' + end_address + '&pw=2';
		
		$('toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter).setStyle('display', 'block');
		$('toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter).addEvent('click', function() {
			window.open(url, 'Print Driving Directions');
		});
	},
	
	/**
	 * Check States
	 * Checks the states of the map element, street element and directions elements.
	 */
	check_states: function(map, street, direction) {
		if ((map && $(this.options.elements.containers.map+'_'+this.options.counter).getStyle('display') == 'none')
			|| (!map && $(this.options.elements.containers.map+'_'+this.options.counter).getStyle('display') == 'block'))
		{
			return false;
		}
		
		if ((street && $(this.options.elements.containers.street+'_'+this.options.counter).getStyle('display') == 'none')
			|| (!street && $(this.options.elements.containers.street+'_'+this.options.counter).getStyle('display') == 'block'))
		{
			return false;
		}
			
		if ((direction && $(this.options.elements.containers.directions+'_'+this.options.counter).getStyle('display') == 'none')
			|| (!direction && $(this.options.elements.containers.directions+'_'+this.options.counter).getStyle('display') == 'block'))
		{
			return false;
		}
		
		return true;
	},
	
	create_markers: function() {
		// Setup the default icon
		this.options.map.markers.icons.default_icon = new google.maps.MarkerImage(
			this.options.elements.other.default_icon,
			new google.maps.Size(22, 28),
			new google.maps.Point(0,0),
			new google.maps.Point(6, 26)
		);
		
		this.options.map.markers.info_windows = [];
		// Now create the markers
		for (var i=0; i<this.options.map.markers.raw_data.length; i++)
		{
			var marker_data = this.options.map.markers.raw_data[i];

			var position = new google.maps.LatLng(marker_data.lat, marker_data.lng);
			var point = new google.maps.Marker({
				position: position,
				map: this.options.map.construct,
				icon: this.options.map.markers.icons.default_icon,
				title: marker_data.title
			});
			
			// Entend the bounds for the makers.
			this.options.map.bounds.extend(position);
			
			this.options.map.markers.points.push(point);
			
			var info_window = new google.maps.InfoWindow({
				content: marker_data.window
			});
			this.options.map.markers.info_windows.push(info_window);
			
			google.maps.event.addListener(point, 'click', (function(markerArg, index) {
				return function() {
					if (this.options.map.markers.current_info_window)
						this.options.map.markers.current_info_window.close();
					this.options.map.markers.info_windows[index].open(this.options.map.construct, this.options.map.markers.points[index]);
					this.options.map.markers.current_info_window = this.options.map.markers.info_windows[index];
				}.bind(this);
			}.bind(this))(point, i));
		}
	},
	
	/**
	 * Init Street View
	 */
	init_street: function(settings) {
		if (settings.streetView)
		{
			this.options.street_view.panarama = new google.maps.StreetViewPanorama( $(this.options.elements.containers.street + '_' + this.options.counter), {
				enableCloseButton: false
			});
			this.options.street_view.service = new google.maps.StreetViewService();
		}
	},
	
	process_street_view: function(data, status) {
		if (status == google.maps.StreetViewStatus.OK)
		{
			this.options.street_view.panarama.setPano(data.location.pano);
			this.options.street_view.panarama.setVisible(true);
		}
		else
		{
			this.street_view_error(status);
		}
	},
	
	street_view_error: function(status) {
		var error = new Array();
		/*
		UNKNOWN_ERROR  	The request could not be successfully processed, yet the exact reason for failure is unknown.
		ZERO_RESULTS 	There are no nearby panoramas.
		*/
		error['UNKNOWN_ERROR'] = "An unknown error occurred when trying to process your request. Please try again.";
		error['ZERO_RESULTS']  = "There are no street view images in the requested area.";
		
		var street_view = $(this.options.elements.containers.street + '_' + this.options.counter);
		street_view.set('html', '').set('style', 'border: 0px;');
		
		var img = new Element('div', { 'class': 'street_view_fail' });
		
		// Create the html for the error message
		var text = new Element('div', {
			'class': 'street_view_fail_text',
			'html': error[status]
		});
		
		img.inject(street_view);
		text.inject(street_view);
	},
	
	/**
	 * Init Driving Directions
	 */
	init_directions: function(settings) {
		this.options.directions.service = new google.maps.DirectionsService();
		this.options.directions.renderer = new google.maps.DirectionsRenderer();

		this.options.directions.renderer.setMap(this.options.map.construct);
    	this.options.directions.renderer.setPanel($(this.options.elements.containers.directions_panel + '_' + this.options.counter));
    	
		// Set the Travel Modes
		this.options.directions.travel_type.BICYCLING = google.maps.DirectionsTravelMode.BICYCLING;
		this.options.directions.travel_type.DRIVING   = google.maps.DirectionsTravelMode.DRIVING;
		this.options.directions.travel_type.WALKING   = google.maps.DirectionsTravelMode.WALKING;
		
		// Start Icon
		if ($defined(settings.elements.start_icon))
		{
			this.options.elements.other.start_icon = settings.elements.start_icon;
			
			this.options.map.markers.icons.start_icon = new google.maps.MarkerImage(
				this.options.elements.other.start_icon,
				new google.maps.Size(35, 43),
				new google.maps.Point(0,0),
				new google.maps.Point(7, 40)
			);
		}
		
		if ($defined(settings.direction_values.start_address))
		{
			$(this.options.elements.inputs.start_address + '_' + this.options.counter).set('value', settings.direction_values.start_address);
		}
		
		var start_address = Cookie.read('directions_start_address');
		if (start_address != '')
		{
			$(this.options.elements.inputs.start_address + '_' + this.options.counter).set('value', start_address);
		}
		
		if ($defined(settings.direction_values.end_address))
		{
			$(this.options.elements.inputs.end_address + '_' + this.options.counter).set('value', settings.direction_values.end_address);
		}
		
	},
	
	do_directions: function() {
		//print_button = 'toggle_' + this.options.elements.buttons.toggle_directions + '_' + this.options.elements.buttons.toggle_print + '_' + this.options.counter;
		
		this.clear_map();
		
		var start_address = $(this.options.elements.inputs.start_address + '_' + this.options.counter).getProperty('value');
		var end_address = $(this.options.elements.inputs.end_address + '_' + this.options.counter).getProperty('value');
		
		if (start_address == '')
		{
			$(this.options.elements.inputs.start_address + '_' + this.options.counter).addClass('error');
			$(this.options.elements.inputs.start_address + '_' + this.options.counter).focus();
		}
		else
		{
			$(this.options.elements.inputs.start_address + '_' + this.options.counter).removeClass('error');
		}
		
		if (end_address == '')
		{
			$(this.options.elements.inputs.end_address + '_' + this.options.counter).addClass('error');
			if (start_address != '')
			{
				$(this.options.elements.inputs.end_address + '_' + this.options.counter).focus();
			}
		}
		else
		{
			$(this.options.elements.inputs.end_address + '_' + this.options.counter).removeClass('error');
		}
		
		if (start_address == '' || end_address == '')
		{
			return;
		}
		
		Cookie.write('directions_start_address', start_address, {duration: 365});

		
		var request = {
			origin: start_address,
			destination: end_address,
			travelMode: this.options.directions.travel_type.DRIVING
		};
		
		this.options.directions.service.route(request, function(response, status) {
			if (status == google.maps.DirectionsStatus.OK)
			{
				this.options.directions.polyline = new google.maps.Polyline({
					path: [],
					strokeColor: '#00CCFF',
					strokeWeight: 3
				});
			
				var bounds = new google.maps.LatLngBounds();
				var route = response.routes[0];
				var directions_panel = $(this.options.elements.containers.directions_panel + '_' + this.options.counter);
				var startLocation = new Object();
				var endLocation = new Object();
		
				var direction_steps = new Element('table', {
					'id' : 'direction_steps_' + this.options.counter,
					'class' : 'direction_steps',
					'border' : 0,
					'cellspacing' : 0
				});
				
				// For each route, display summary information.
				for (var i=0; i<route.legs.length; i++)
				{					
					var tr = new Element('tr');
					
					var start_address_td = new Element('td', {
						'class' : 'start_address',
						'colspan' : 2,
						'html'  : route.legs[i].start_address
					})
					
					start_address_td.inject(tr);
					tr.inject(direction_steps);
					
					var distance_tr = new Element('tr');
				
					var distance = new Element('td', {
						'class' : 'total_distance',
						'colspan' : 2,
						'html' : route.legs[i].distance.text + ' - about ' + route.legs[i].duration.text
					});
					
					distance.inject(distance_tr);
					
					var end_address_tr = new Element('tr');
						
					var end_address_td = new Element('td', {
						'class' : 'end_address',
						'colspan' : 2,
						'html'  : route.legs[i].end_address
					})
					
					end_address_td.inject(end_address_tr);
					
					var copyright_div = new Element('div', {
						'class' : 'copyright',
						'html' : route.copyrights
					});
				}
		
				var path = response.routes[0].overview_path;
				var legs = response.routes[0].legs;
				for (i=0; i<legs.length; i++)
				{
					if (i == 0)
					{ 
						startLocation.latlng = legs[i].start_location;
						startLocation.address = legs[i].start_address;
						this.create_direction_marker(legs[i].start_location,"start",legs[i].start_address);
					}
			
					endLocation.latlng = legs[i].end_location;
					endLocation.address = legs[i].end_address;
					var steps = legs[i].steps;
					for (j=0; j<steps.length; j++)
					{
					 	var odd = false
					 	var tr_class = 'step even';
						if (j%2)
						{
							odd = true;
					 		tr_class = 'step odd';
						}
					
						var nextSegment = steps[j].path;
						var tr = new Element('tr', {
							'id' : 'step_' + j,
							'class' : tr_class
						});
						
						var td_instructions = new Element('td', {
							'class' : 'instructions ' + tr_class,
							'html' : (j+1) + ". " + steps[j].instructions
						});
						
						var td_distance_html = '';
						if (steps[j].distance && steps[j].distance.text)
						{
							td_distance_html = steps[j].distance.text;
						}
						
						var td_distance = new Element('td', {
							'class' : 'distance ' + tr_class,
							'html' : td_distance_html,
							'nowrap' : 'nowrap'
						});
						
						td_instructions.inject(tr);
						td_distance.inject(tr);
						tr.inject(direction_steps);
						
						for (k=0; k<nextSegment.length; k++)
						{
							this.options.directions.polyline.getPath().push(nextSegment[k]);
							bounds.extend(nextSegment[k]);
						}
					}
				}
				
				distance_tr.inject(direction_steps);
				end_address_tr.inject(direction_steps);
				direction_steps.inject(directions_panel);
				copyright_div.inject(directions_panel);

				this.options.directions.polyline.setMap(this.options.map.construct);
				this.options.map.construct.fitBounds(bounds);
				this.create_direction_marker(endLocation.latlng,"end",endLocation.address);
				
				this.print_map(startLocation.address, endLocation.address);
			}
			else
			{
				this.directions_error(status);
			}
		}.bind(this));
	},
	
	directions_error: function(status) {
		var error = new Array();
		/*
		INVALID_REQUEST  		The DirectionsRequest provided was invalid.
		MAX_WAYPOINTS_EXCEEDED 	Too many DirectionsWaypoints were provided in the DirectionsRequest. The total allowed waypoints is 8, plus the origin and destination.
		NOT_FOUND 				At least one of the origin, destination, or waypoints could not be geocoded.
		OVER_QUERY_LIMIT 		The webpage has gone over the requests limit in too short a period of time.
		REQUEST_DENIED 			The webpage is not allowed to use the directions service.
		UNKNOWN_ERROR 			A directions request could not be processed due to a server error. The request may succeed if you try again.
		ZERO_RESULTS 			No route could be found between the origin and destination.
		*/
		error['INVALID_REQUEST'] 		= "The address supplied was not a known address and no result could be found";
		error['MAX_WAYPOINTS_EXCEEDED'] = "You requested more than the maximum 8 waypoints, please remove some and try again.";
		error['NOT_FOUND'] 				= "The address supplied could not be found";
		error['OVER_QUERY_LIMIT'] 		= "Too many requests, please try again later.";
		error['REQUEST_DENIED'] 		= "This site is not authorized to use the directions service.";
		error['UNKNOWN_ERROR'] 			= "We were not able to retrieve results for this request. Please try again.";
		error['ZERO_RESULTS'] 			= "No route could be found between the start and destination addresses.";
		
		var directions_panel = $(this.options.elements.containers.directions_panel + '_' + this.options.counter);
		
		var img = new Element('div', { 'class': 'directions_fail' });
		
		// Create the html for the error message
		var text = new Element('div', {
			'class': 'directions_fail_text',
			'html': error[status]
		});
		
		img.inject(directions_panel);
		text.inject(directions_panel);
	},
	
	create_direction_marker: function(latlng, label, html) {
		var icon = this.options.map.markers.icons.default_icon;
		if (label == 'start')
		{
			icon = this.options.map.markers.icons.start_icon;
		}
	
		var contentString = '<b>'+label+'</b><br>'+html;
		var marker = new google.maps.Marker({
			position: latlng,
			map: this.options.map.construct,
			icon: icon,
			title: label
		});
		marker.myname = label;
		this.options.directions.markers.push(marker);
		
		google.maps.event.addListener(marker, 'click', function() {
			infowindow.setContent(contentString); 
			infowindow.open(this.options.map.construct,marker);
		});
	},
	
	clear_map: function() {
		// Remove normal markers
		for(var i=0; i<this.options.map.markers.points.length; i++)
		{
			this.options.map.markers.points[i].setMap(null);
		}
		
		if (this.options.directions.status)
		{
			// Make sure the direction markers are cleared too
			for(var i=0; i<this.options.directions.markers.length; i++)
			{
				this.options.directions.markers[i].setMap(null);
			}
			
			// And don't forget any poly lines for the directions
			if (this.options.directions.polyline)
			{
				this.options.directions.polyline.setMap(null);
			}
			
			$(this.options.elements.containers.directions_panel + '_' + this.options.counter).set('html', '');
		}
	}
});

var interactive_controls = new Class({

	Implements: [Events, Options],
	
	map: null, // The map class is loaded into here for later use
	
	values: {
		center: null,
		markers: {
			points: [],
			info_windows: []
		},
		polyline: [],
		polygon: []
	}
});
