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

var Map = {
	DEFAULT_ZOOM: 3,
	DEFAULT_RADIUS: 3500,
	DEFAULT_BASE_URL: 'http://locator.bulletproofdiesel.com/locator',
	SEARCH_RESULT_TEMPLATE: new Template(
		''
		+ '<div class="map_stores_result #{special_store_class}">'
		+ '	<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}">&#8250; 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;">&#8250; Get driving directions</a></div>'		
		+ '</div>'										
	),
	SEARCH_RESULT_STORES_TEMPLATE: new Template('#{num} stores in your area'),
	SEARCH_RESULT_HEIGHT: 107,
	INFO_WINDOW_TEMPLATE: new Template(
		''
		+ '<div class="map_stores_result_infowindow">'
		+ '	<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: 247,
	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://locator.bulletproofdiesel.com/locator/search-locations.php',
	ICON_URL: 'http://locator.bulletproofdiesel.com/locator/icons.php',
	MISSING_LOCATIONS_URL: 'http://locator.bulletproofdiesel.com/locator/missing-locations.php',
	
	obj: null,
	icon: null,
	geocoder: null,
	currentPage: 0,
	currentPages: 0,	
	elements: $H({}),
	icons: null, 
	
	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(23, 24);
		Map.icon.shadow = Map.DEFAULT_BASE_URL+'/images/markers/transparent.png';
		Map.icon.shadowSize = new google.maps.Size(23, 25);
		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];
		
		/* Load special icons */
		Map.loadIcons();
		/*--------------------------------------------------------------------------*
		 * 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').addClassName('map_zoom_control');
			var panUp = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_up.gif',
				alt: 'Up',
				title: 'Up'
			}).addClassName('map_zoom_control_col_1');
			var panDown = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_down.gif',
				alt: 'Down',
				title: 'Down'
			}).addClassName('map_zoom_control_col_1');
			var panLeft = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_left.gif',
				alt: 'Left',
				title: 'Left'
			}).addClassName('map_zoom_control_col_1');
			var panRight = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/pan_right.gif',
				alt: 'Right',
				title: 'Right'
			}).addClassName('map_zoom_control_col_2');
			var zoomIn = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/zoom_in.gif',
				alt: 'In',
				title: 'In'
			}).addClassName('map_zoom_control_col_1');
			var zoomOut = new Element('input', {
				type: 'image', 
				src: Map.DEFAULT_BASE_URL+'/images/controls/zoom_out.gif',
				alt: 'Out',
				title: 'Out'
			}).addClassName('map_zoom_control_col_1');					
			var containerRows = [
				new Element('div').addClassName('map_zoom_control_row_1'),
				new Element('div').addClassName('map_zoom_control_row_2'),
				new Element('div').addClassName('map_zoom_control_row_3'),
				new Element('div').addClassName('map_zoom_control_row_4'),
				new Element('div').addClassName('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').addClassName('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);
		$$('#map_search_bottom input').each(function(cb){
			Event.observe(cb, 'change', Map.searchButtonClicked);	
		});
		
		//Set default location (if available)
		Map.searchClientLocation();		
	},
	
	loadIcons: function(callback, arg1){
		new Ajax.Request(Map.ICON_URL,{
			method: 'get',
			evalJSON: true,
			sanitizeJSON: true,
			onSuccess: function(transport) {
				try{
					var tmpHash = $H();
					if(transport.responseJSON !== null){
						transport.responseJSON.each(function(iconData){
							var icon = new google.maps.Icon(Map.icon);
							icon.image = Map.DEFAULT_BASE_URL + iconData.image;							
							tmpHash.set(iconData.id, icon);					
						});
					}
					Map.icons = tmpHash;
				
					if(typeof callback == "function"){
						callback(arg1);
					}	
				}
				catch(e){/*No-op*/console.log(e)}
			},
			onFailure: function(){
				Map.icons = $H();
			}			
		});
		
		
	},
	
	unload: function() {
		google.maps.Unload();
	},
		
	searchClientLocation: function() {
		//See if we have a location
		if(!google.loader.ClientLocation || google.loader.ClientLocation == null) {
			Map.search(
					'39.5', 
					'-98.35',
					Map.DEFAULT_RADIUS
			);
		}
		
		//Search using client location		
		Map.search(
			google.loader.ClientLocation.latitude, 
			google.loader.ClientLocation.longitude,
			Map.DEFAULT_RADIUS,
			true
		);
	},
	
	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)*4*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)*4*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
		if(event !== null && event !== undefined){
			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, centerUSA) {
		//Set the center
		if(centerUSA == true){
			Map.obj.setCenter(new google.maps.LatLng('39.5', '-98.35'), Map.DEFAULT_ZOOM);
		}
		else{
			Map.obj.setCenter(new google.maps.LatLng(latitude, longitude), Map.DEFAULT_ZOOM);
		}
		
		var types = [];
		
		$$('#map_search_form input[name="type"]').findAll(function(e){
		    return e.checked;
		}).each(function(cb){
			types.push(cb.value);			
		});
		new Ajax.Request(Map.SEARCH_URL, {
			method: 'get',
			parameters: {latitude: latitude, longitude: longitude, radius: radius, 'type[]': types},
			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*/console.log(e)}
					
					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) {
		var storesText = '';
		//No object, exit
		if(locations == null) {
			return;
		}
		
		//Check if the special markers are loaded. If not load them and recall this function.
		if(Map.icons === null){
			Map.loadIcons(Map.showLocations, locations);
			return;
		}; 
		
		//Wipe out previous data
		Map.clearLocations();

	
		//Update the number of stores
		storesText = Map.SEARCH_RESULT_STORES_TEMPLATE.evaluate({num: locations.size()});
		Map.elements.get('stores').update(storesText);

		//Update the pagingation
		Map.currentPage = (locations.size() <= 0 ? 0:1);
		Map.currentPages = Math.ceil(locations.size() / 4.0);
		Map.updatePagesDisplay();
		
		//Go through each location		
		locations.each(function(item) {
			var marker = null;
			var infoWindowHtml = null;
			
			var itemIcon = Map.icon;
			
			if(parseInt(item.icon_id) !== 0){
				if(Map.icons.get(item.icon_id) !== undefined && Map.icons.get(item.icon_id) !== null){
					itemIcon = Map.icons.get(item.icon_id);
				}
			}
			
			//Create marker			
			marker = new google.maps.Marker(
				new google.maps.LatLng(item.latitude, item.longitude), 
				{icon: itemIcon}
			);
			
			//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*/console.log(e)}
		});
	}
};

/*--------------------------------------------------------------------------*
 * 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);
