/*--------------------------------------------------------------------------*
 * 
 * Copyright (C) 2008 Brand Labs LLC
 * 
 *--------------------------------------------------------------------------*/

var Map = {
	DEFAULT_ZOOM: 9,
	DEFAULT_RADIUS: 25,
	DEFAULT_BASE_URL: 'http://custom.doctorsfinest.com',
	
	SEARCH_RESULT_TEMPLATE: new Template(
		''
		+ '<div class="map_stores_result">'
		+ '	<div class="map_stores_result_title"><h4 title="#{name}">#{name}</h4></div>'
		+ '	<div class="map_stores_result_address">#{address1}</div>'
		+ '	<div class="map_stores_result_address">#{city} #{state},  #{zipcode}</div>'
		+ '	<div class="map_stores_result_address">#{phone_number}</div>'
		+ '	<div class="map_stores_result_link"><a href="javascript: void(0);" id="map_stores_show_on_map_#{location_id}">Show on map</a></div>'
		+ '	<div class="map_stores_result_link"><a href="http://maps.google.com/?q=#{urlEncodedAddress}" onclick="javascript: window.open(this.href); return false;">Get driving directions</a></div>'		
		+ '</div>'										
	),
	SEARCH_RESULT_HEIGHT: 105,
	INFO_WINDOW_TEMPLATE: new Template(
		''
		+ '<div class="map_stores_result">'
		+ '	<h4 title="#{name}">#{name}</h4>'
		+ '	<div class="map_stores_result_address">#{address1}</div>'
		+ '	<div class="map_stores_result_address">#{address2}</div>'
		+ '	<div class="map_stores_result_address">#{city} #{state},  #{zipcode}</div>'
		+ '	<div class="map_stores_result_address">#{phone_number}</div>'
		+ '</div>'										
	),
	INFO_WINDOW_MAX_WIDTH: 187,
	PAGINATION_TEMPLATE: new Template('Showing Page #{page} of #{pages}'),	
	ELEMENT_NAMES: $H({
		'map': 'map_middle_left',
		'search_button': 'map_search_button',
		'search_form': 'map_search_form',
		'previous_button': 'map_previous_button',
		'next_button': 'map_next_button',
		'results_scroll': 'map_stores_results_scroll',
		'results_scrolling': 'map_stores_results_scrolling',
		'pages': 'map_stores_pages',
		'stores': 'map_stores',
		'address': 'map_search_address',
		'radius': 'map_search_radius'
	}),
	SEARCH_URL: 'http://custom.doctorsfinest.com/search-locations.php5',
	MISSING_LOCATIONS_URL: 'http://custom.doctorsfinest.com/missing-locations.php5',
	
	obj: null,
	icon: null,
	geocoder: null,
	currentPage: 0,
	currentPages: 0,	
	elements: $H({}),
	
	load: function() {
		//Exit if not compatiable
		if(!google.maps.BrowserIsCompatible()) {
			return;
		}
		
		//Load elements
		Map.ELEMENT_NAMES.each(function(pair) {
			Map.elements.set(pair.key, $(pair.value));
		});
		
		//Create the actual map
		Map.obj = new google.maps.Map2(Map.elements.get('map'));
		
		//Create the address coder
		Map.geocoder = new google.maps.ClientGeocoder();
		
		//Create custom marker
		Map.icon = new google.maps.Icon(G_DEFAULT_ICON);
		Map.icon.image = Map.DEFAULT_BASE_URL+'/images/markers/image.png';
		Map.icon.iconSize = new google.maps.Size(36, 33);
		Map.icon.shadow = Map.DEFAULT_BASE_URL+'/images/markers/shadow.png';
		Map.icon.shadowSize = new google.maps.Size(40, 37);
		Map.icon.iconAnchor = new google.maps.Point(18, 32);
		Map.icon.infoWindowAnchor = new google.maps.Point(17, 0);		
		Map.icon.transparent = Map.DEFAULT_BASE_URL+'/images/markers/transparent.png';
		Map.icon.printImage = Map.DEFAULT_BASE_URL+'/images/markers/printImage.gif';
		Map.icon.mozPrintImage = Map.DEFAULT_BASE_URL+'/images/markers/mozPrintImage.gif';
		Map.icon.imageMap = [16,30, 15,29, 14,28, 11,28, 7,26, 3,22, 1,20, 0,17, 0,13, 1,10, 2,8, 3,6, 6,4, 9,2, 12,1, 18,0, 22,0, 25,1, 27,2, 29,3, 31,5, 32,6, 34,8, 35,9, 36,12, 36,18, 36,19, 35,20, 34,21, 32,23, 30,25, 26,27, 25,28, 22,28, 20,29, 19,33, 18,33];


		/*--------------------------------------------------------------------------*
		 * Setup zoom and pan controls
		 *--------------------------------------------------------------------------*/
		MapZoomControl.prototype = new google.maps.Control();
		MapZoomControl.prototype.getDefaultPosition = function() {
			return new google.maps.ControlPosition(G_ANCHOR_TOP_LEFT, new google.maps.Size(0, 0));
		};
		MapZoomControl.prototype.initialize = function(map) {
			var container = new Element('div', {'class': 'map_zoom_control'});
			var panUp = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_up.png',
				alt: 'Up',
				title: 'Up',
				'class': 'map_zoom_control_col_1'
			});
			var panDown = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_down.png',
				alt: 'Down',
				title: 'Down',
				'class': 'map_zoom_control_col_1'
			});
			var panLeft = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_left.png',
				alt: 'Left',
				title: 'Left',
				'class': 'map_zoom_control_col_1'
			});
			var panRight = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_right.png',
				alt: 'Right',
				title: 'Right',
				'class': 'map_zoom_control_col_2'
			});
			var zoomIn = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/zoom_in.png',
				alt: 'In',
				title: 'In',
				'class': 'map_zoom_control_col_1'
			});
			var zoomOut = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/zoom_out.png',
				alt: 'Out',
				title: 'Out',
				'class': 'map_zoom_control_col_1'
			});						
			var containerRows = [
				new Element('div', {'class': 'map_zoom_control_row_1'}),
				new Element('div', {'class': 'map_zoom_control_row_2'}),
				new Element('div', {'class': 'map_zoom_control_row_3'}),
				new Element('div', {'class': 'map_zoom_control_row_4'}),
				new Element('div', {'class': 'map_zoom_control_row_5'})
			];							
			
			//Add everything together
			containerRows[0].insert(panUp);
			containerRows[1].insert(panLeft);
			containerRows[1].insert(panRight);
			containerRows[2].insert(panDown);
			containerRows[3].insert(zoomIn);
			containerRows[4].insert(zoomOut);
			containerRows.each(function(row){
				container.insert(row);
			});
			//Add to the main container
			map.getContainer().appendChild(container);
			
			//Setup events
			panUp.observe('click', function() {
				map.panDirection(0, 1);
			});
			panDown.observe('click', function() {
				map.panDirection(0, -1);
			});
			panLeft.observe('click', function() {
				map.panDirection(1, 0);
			});
			panRight.observe('click', function() {
				map.panDirection(-1, 0);
			});
			zoomIn.observe('click', function() {
				map.zoomIn();
			});
			zoomOut.observe('click', function() {
				map.zoomOut();
			});							
			
			return container;
		};
		/*--------------------------------------------------------------------------*/


		/*--------------------------------------------------------------------------*
		 * Setup zoom and pan controls
		 *--------------------------------------------------------------------------*/
		MapTypeControl.prototype = new google.maps.Control();
		MapTypeControl.prototype.getDefaultPosition = function() {
			return new google.maps.ControlPosition(G_ANCHOR_TOP_RIGHT, new google.maps.Size(0, 0));
		};
		MapTypeControl.prototype.initialize = function(map) {
			var container = new Element('div', {'class': 'map_type_control'});			
			var mapButton = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/type_map_off.gif',
				alt: 'Map',
				title: 'Map'
			});
			var satelliteButton = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/type_satellite_off.gif',
				alt: 'Satellite',
				title: 'Satellite'
			});
			var hybridButton = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/type_hybrid_off.gif',
				alt: 'Hybrid',
				title: 'Hybrid'
			});			
			
			//Add everything together
			container.insert(mapButton);
			container.insert(satelliteButton);
			container.insert(hybridButton);
			//Add to the main container
			map.getContainer().appendChild(container);
			
			//Setup events
			mapButton.observe('click', function() {
				map.setMapType(G_NORMAL_MAP);
			});				
			satelliteButton.observe('click', function() {
				map.setMapType(G_SATELLITE_MAP);
			});	
			hybridButton.observe('click', function() {
				map.setMapType(G_HYBRID_MAP);
			});
			
			//Listeners for changes
			google.maps.Event.addListener(map, 'maptypechanged', function() {
				switch(map.getCurrentMapType()) {
					case G_NORMAL_MAP:
						mapButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_map_on.gif';
					break;
					
					default: 
						mapButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_map_off.gif';
					break;
				}
			});
			google.maps.Event.addListener(map, 'maptypechanged', function() {
				switch(map.getCurrentMapType()) {
					case G_SATELLITE_MAP:
						satelliteButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_satellite_on.gif';
					break;
					
					default: 
						satelliteButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_satellite_off.gif';
					break;
				}
			});
			google.maps.Event.addListener(map, 'maptypechanged', function() {
				switch(map.getCurrentMapType()) {
					case G_HYBRID_MAP:
						hybridButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_hybrid_on.gif';
					break;
					
					default: 
						hybridButton.src = Map.DEFAULT_BASE_URL+'/images/controls/type_hybrid_off.gif';
					break;
				}
			});						
			
			return container;
		};
		/*--------------------------------------------------------------------------*/


		//Add controls
        Map.obj.addControl(new MapTypeControl());
		Map.obj.addControl(new MapZoomControl());
		
		//Setup events
		Event.observe(Map.elements.get('search_form'), 'submit', Map.searchButtonClicked);
		Event.observe(Map.elements.get('previous_button'), 'click', Map.previousPageClicked);
		Event.observe(Map.elements.get('next_button'), 'click', Map.nextPageClicked);
		
		//Set default location (if available)
		Map.searchClientLocation();		
	},
	
	unload: function() {
		google.maps.Unload();
	},
	
	searchClientLocation: function() {
		//See if we have a location
		if(!google.loader.ClientLocation || google.loader.ClientLocation == null) {
			return;
		}
		
		//Search using client location		
		Map.search(
			google.loader.ClientLocation.latitude, 
			google.loader.ClientLocation.longitude,
			Map.DEFAULT_RADIUS
		);
	},
	
	previousPageClicked: function() {
		//No more pages
		if(Map.currentPage <= 1) {
			return;
		}
		
		//Increment page count
		Map.currentPage--;
		
		//Adjust location
		Map.elements.get('results_scroll').setStyle({
			'top': -((Map.currentPage-1)*3*Map.SEARCH_RESULT_HEIGHT) + 'px'
		});
		
		//Update display
		Map.updatePagesDisplay();		
	},
	
	nextPageClicked: function() {
		if(Map.currentPage == null || Map.currentPages == null) {
			return;
		}
		
		//No more pages
		if(Map.currentPage >= Map.currentPages) {
			return;
		}
		
		//Increment page count
		Map.currentPage++;
		
		//Adjust location
		Map.elements.get('results_scroll').setStyle({
			'top': -((Map.currentPage-1)*3*Map.SEARCH_RESULT_HEIGHT) + 'px'
		});
		
		//Update display
		Map.updatePagesDisplay();
	},
	
	updatePagesDisplay: function() {
		var page = null;
		var pages = null;
		
		page = Map.currentPage;
		pages = Map.currentPages;
		
		if(page == null || pages == null) {
			return;
		}
		
		//Update the pagingation
		$(Map.elements.get('pages')).update(Map.PAGINATION_TEMPLATE.evaluate({page: page, pages: pages}));		
	},	
	
	searchButtonClicked: function(event) {
		//Cancel event
		Event.stop(event);
				
		Map.geocoder.getLatLng($F(Map.elements.get('address')), function(latLng) {
			var radius = null;
			
			if(!latLng || latLng == null) {
				//TODO
				return;
			}
			
			//Get radius
			radius = $F(Map.elements.get('radius'));			
			if(radius == null) {
				radius = Map.DEFAULT_RADIUS;
			}
			
			//Send off search request
			Map.search(latLng.lat(), latLng.lng(), radius);
		});		
	},
	
	search: function(latitude, longitude, radius) {
		//Set the center
		Map.obj.setCenter(new google.maps.LatLng(latitude, longitude), Map.DEFAULT_ZOOM);
		
		new Ajax.Request(Map.SEARCH_URL, {
			method: 'get',
			parameters: {latitude: latitude, longitude: longitude, radius: radius},
			evalJSON: true,
			sanitizeJSON: true,
			onSuccess: function(transport) {
				if (transport.responseJSON == null) {
					Map.showLocations(new Array());
					
					//Log the missing store
					try {
						Map.logMissingLocations(latitude, longitude);
					} catch(e) {/*No-op*/}
					
					return;
				}
				
				Map.showLocations(transport.responseJSON);
			}
		});
	},
	
	clearLocations: function() {
		//Erase previous markers
		Map.obj.clearOverlays();
		
		//Empty content area
		Map.elements.get('results_scroll').update('');
		Map.elements.get('stores').update('');
		Map.elements.get('pages').update('');
		
		Map.elements.get('results_scroll').setStyle({'top': '0px'});
	},
	
	showLocations: function(locations) {
		//No object, exit
		if(locations == null) {
			return;
		}
		
		//Wipe out previous data
		Map.clearLocations();

	
		//Update the number of stores
		Map.elements.get('stores').update(locations.size());

		//Update the pagingation
		Map.currentPage = (locations.size() <= 0 ? 0:1);
		Map.currentPages = Math.ceil(locations.size() / 3.0);
		Map.updatePagesDisplay();
		
		//Go through each location		
		locations.each(function(item) {
			var marker = null;
			var infoWindowHtml = null;

			//Create marker			
			marker = new google.maps.Marker(
				new google.maps.LatLng(item.latitude, item.longitude), 
				{icon: Map.icon}
			);
			
			//Create the URL encoded address for linking
			item.urlEncodedAddress = escape(item.address1 + ' ' + item.city + ' ' + item.state + ', ' + item.zipcode);

			//Create HTML for info window
			infoWindowHtml = Map.INFO_WINDOW_TEMPLATE.evaluate(item);
						
			Map.elements.get('results_scroll').insert(Map.SEARCH_RESULT_TEMPLATE.evaluate(item));
			google.maps.Event.addListener(marker, 'click', function() {
				marker.openInfoWindowHtml(infoWindowHtml, {maxWidth: Map.INFO_WINDOW_MAX_WIDTH});
			});	
			Event.observe($('map_stores_show_on_map_'+item.location_id), 'click', function() {
				//Trigger another event through DOM
				google.maps.Event.trigger(marker, 'click');
			});
			
			//Add to map
			Map.obj.addOverlay(marker);			
		});
	},
	
	logMissingLocations: function(latitude, longitude) {
		new Ajax.Request(Map.MISSING_LOCATIONS_URL, {
			method: 'post',
			parameters: {
				latitude: latitude,
				longitude: longitude
			},
			onSuccess: function(transport){/*No-op*/}
		});
	}
};

/*--------------------------------------------------------------------------*
 * Zoom control
 *--------------------------------------------------------------------------*/
function MapZoomControl(){};
/*--------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*
 * Type control
 *--------------------------------------------------------------------------*/
function MapTypeControl(){};
/*--------------------------------------------------------------------------*/


//Load the map functionality
google.load('maps', '2');

//Setup load and unload functions
Event.observe(window, 'load', Map.load);
Event.observe(window, 'unload', Map.unload);
