//------------------------------------
//
//	ENGAGE.LOCATION.JS
//	Author: 	Engage Interactive
//	Requires:	jquery 1.6
//				engage.findmynearest
//	Version:	2
//	To-Do:		Re-do how each result is created. At the moment there is a lot of unnecessary code repitition. Make it a function.
//
//------------------------------------


(function($){

	//////////////////////////
	// GLOBAL VARIABLES
	
	var mooseBan = false;
	var searchBan = false;
	
	var error = false;
	var result = false;
	var bar = false;
	
	
	//////////////////////////
	// BEGIN PLUGIN
	
	jQuery.fn.location = function (settings){
	
		//////////////////////////
		// DEFAULTS
		var defaults = {
			'json':					'/locations/json',
			'url':					'[location]',
			'results':				4,
			'alternate_results':	4,
			'all_results':			4,
			'delayIn':				.15,
			'delayOut':				.08,
			'overlay':				.7,
			'ready':				function(){},	// Gets called once, when plugin is activated
			'before':				function(){}	// Gets called each time the location picker is shown, but only if there are changes to text. For cufon.
		};

		// Combine defaults with settings
		var o = $.extend(defaults, settings);
		
		// Not that there will ever be multiple search forms, but there are multiple times this gets called
		return this.each(function(){

			// Objects
			var $form = $(this);
			var $input = $form.find('input');
			var $overlay = $('#overlay');
			var $loading = $overlay.find('.loading');
			var $message;
			var $results = $('#search_results');
			var $wrapper = $('#results_wrapper'); // This is only used in the non-exciting, non-3d versions of events
			var $bar = $results.find('span.top_border');
			var $close;
			
			// Variables
			var cHeight;
			var fancy3d = $('html').hasClass('webkit');
	
			
			// Permenantly set overlay opacity
			$overlay.find('.background').css({
				'opacity':	o.overlay
			});
			
			
			//////////////////////////
			// INPUT TYPING
			
			$input.bind({
				'keydown':	function(){
				
					$form.removeClass('active');
				
				}
			});
			
			
			//////////////////////////
			// ACTIVATE SEARCH
	
			function activateSearch(){
			
				// Get the nice name
				if( o.brand == 'classic' || o.brand == undefined ) var niceName = 'Restaurant';
				else if( o.brand == 'cafe' ) var niceName = 'Caf&eacute;';
				else if( o.brand == 'stop' ) var niceName = 'Stop';
				else if( o.brand == 'burgers' ) var niceName = 'Burgers';
				else if( o.brand == 'barandgrill' ) var niceName = 'Bar &amp; Grill';
				
				// Some wording
				var mainTitle = '<h2>Your nearest Giraffe ' + niceName + '</h2>';
				var secondaryTitle = '<h2>Or try one of our other brands&hellip;</h2>';
				
				// Global total
				var total;
				
				// Unbind the previous submit, and apply another so that we use current settings
				$form.submit(function(e){
					
					// Get the search term
					$search_term = $input.val();
	
					// Disable if in the middle of search or Google Maps not loaded
					if( searchBan || !googleMapsEnabled ) return false;
					
					else searchBan = true;
					
					// If the form has already been used, and is unchanged since that time, we clear the results
					if( $form.hasClass('active') ){
					
						// Focs the input and empty it
						$input.val('').focus();
						
						// Remove the active class
						$form.removeClass('active');
					
						if( result ){
						
							// Hide the results
							hideResults(function(){
		
								// Unban the search
								searchBan = false;
								
								// Clean stuff up
								cleanup();
		
							});
							
						}else if( error ){
						
							// Hide the message
							message('hide',function(){
		
								// Unban the search
								searchBan = false;
								
								// Clean stuff up
								cleanup();
		
							});
						
						}
						
					
					}else{
					
						// Form is active (this adds the little cross and helps work out a few other things)
						$form.addClass('active');
						
						// Fade out the page
						$overlay.fadeIn(200);
						
						// Set loading to false, if it is made true, the spinner doesn't show
						var loaded = false;
						
						// Show a loading spinner if the search takes over 400ms
						setTimeout(function(){
						
							if( !loaded ){
								$loading.fadeIn(100);
							}
						
						},200);
						
						// Start search
						findMyNearest($search_term, {
							dataSource:		o.json,
							brand:			o.brand,
							logger:			false,
							onBlank:		function() {
								
								message('Oops&hellip;','To find your nearest Giraffe you need to enter a search term. Why not try:',true);
								
							},
							onNoResult:		function() {
								
								message('Sorry, we don&rsquo;t know where that is&hellip;','Why not try searching one of the following:',true);
								
							},
							onLondon:		function() {
								
								message('Sorry&hellip;','There are a lot of Giraffe&rsquo;s roaming about London, please be a bit more specific! For example, try entering a London landmark such as &lsquo;Nelsons Column&rsquo;.',false);
								
							},
							onResult:		function(brand_results, other_results) {
								
								// Set loaded
								loaded = true;
								
								// Remove loading if it is visible
								$loading.fadeOut(100);
								
								if( fancy3d ){
								
									//////////////////////////
									// 3D VERSION
								
									// We need a count to work out the number of results and other things
									var delay = 0;
									
									// Create the first line of the flip
									var html = '<div class="flip title" style="-webkit-animation-delay: 0s;">' + mainTitle;
									
									// Current brands
									for( var brand_key in brand_results ){
			
										delay++;
			
										html += buildResult(brand_results[brand_key].brand,brand_results[brand_key].name,brand_results[brand_key].distance,brand_results[brand_key].slug,true);
			
									}
									
									// Only do the next part if we have alternatives
									if( other_results != 'all' ){

										// Increase the delay for the title
										delay++;
										
										// Title
										html += '<div class="flip title" style="-webkit-animation-delay: ' + ( o.delayIn * delay ) + 's;">' + secondaryTitle;
									
										// Other brands
										for( var other_key in other_results ){
											
											delay++;
				
											html += buildResult(other_results[other_key].brand,other_results[other_key].name,other_results[other_key].distance,other_results[other_key].slug,true);
				
										}
									
									}
									
									// We now add in the closing div's for all those open flip divs.
									for( i = 0; i <= delay; i++ ){
										html += '</div>';
									}
									
									total = delay;
								
								}else{
								
									//////////////////////////
									// NON 3D VERSION
									
									// Create the first line
									var html = '<div id="results_wrapper">' + mainTitle;
									
									for( var brand_key in brand_results ){
			
										html += buildResult(brand_results[brand_key].brand,brand_results[brand_key].name,brand_results[brand_key].distance,brand_results[brand_key].slug,false);
			
									}
									
									// Only do the next part if we have alternatives
									if( other_results != 'all' ){
									
										// Title
										html += secondaryTitle;
										
										// Other brands
										for( var other_key in other_results ){
											
											html += buildResult(other_results[other_key].brand,other_results[other_key].name,other_results[other_key].distance,other_results[other_key].slug,false);
				
										}
									
									}
									
									// Close the wrapper
									html += '</div>';
								
								}
								
								// Build the individual results
								function buildResult(sBrand,lBrand,dist,slug,threeD){
								
									threeD = threeD ? '<div class="flip" style="-webkit-animation-delay: ' + ( o.delayIn * delay ) + 's;">' : '';
									
									var brandType = o.brand == sBrand ? '' : ' <span>(' + eab(sBrand) + ')</span>';
									
									function eab(b){
									
										if( b == 'barandgrill' ) b = 'Bar &amp; Grill';
										else if( b == 'classic' ) b = 'Classic';
										else if( b == 'burgers' ) b = 'Burgers';
										else if( b == 'cafe' ) b = 'Caf&eacute;';
										else if( b == 'stop' ) b = 'Stop';
										
										return 'Giraffe ' + b;
										
									}
									
									return threeD + '<div class="result"><span class="brand ' + sBrand + '"></span><h3>' + lBrand + brandType + '</h3><small class="icon pin">' + dist + ' miles</small><a href="/' + sBrand + '/location/' + o.url.replace('[location]',slug) + '" class="white_link">Visit location</a></div>';
								
								}
		
								// Show the results container
								$results.show();
								
								// Do we need to do the bar?
								if( !bar ){
														
									// Start the ANIMATING!
									$bar.css({
										'width':	$form.outerWidth(),
										'height':	0
									}).animate({
										'height':	4
									},50,'easeInOutExpo',function(){
										
										$bar.animate({
											'width':	960
										},400,'easeInOutExpo',function(){
										
											buildResults();
											
										});
										
									});
								
								}else{
								
									buildResults();
								
								}
								
								function buildResults(){
								
									// Hide any messages
									if( error ){
									
										message('hide');
									
									}
									
									if( result ){
									
										hideResults(function(){
											beginBuild();
										});
										
									}else{
									
										beginBuild();
									
									}
								
									function beginBuild(){
										
										// Remove any existing results, if there are any by accident, bug.
										$results.find('.flip:first').remove();
										$results.find('#results_wrapper').remove();
									
										// Add in the new results
										$results.prepend(html);
										
										if( fancy3d ){
										
											//////////////////////////
											// 3D VERSION
											
											// Find the last flip
											var $last = $results.children('.flip');
			
											while( $last.length ){
											    $last = $last.children('.flip');
											}
											
											$last.end().bind({
												'webkitAnimationEnd':	function(){
													
													// Remove this listener
													$(this).unbind('webkitAnimationEnd');
													
													// Remove the flipDown animation class, and use the static active class
													$results.removeClass('flipdown').addClass('active');
													
													endBuild();
		
												}
											}).find('.result').addClass('last');
											
											$results.addClass('flipdown');
										
										}else{
										
											//////////////////////////
											// NON 3D VERSION
											
											$wrapper = $('#results_wrapper');
											
											// Add the class of last
											$results.find('.result:last-child').addClass('last');
											
											// Animate this sucka!
											var wHeight = $wrapper.height();
											
											$wrapper.css({
												'height':	0
											}).animate({
												'height':	wHeight
											},600,'easeInOutExpo',function(){
											
												// Clean stuff up for later
												$wrapper.removeAttr('style');
												
												// End the build
												endBuild();
											
											});
											
										}
										
										// Activate the full clickable link thingy
										$results.find('.result').click(function(){
											window.location = $(this).find('.white_link').attr('href');
										});
										
									}
									
									
									// Show the close toggle, set some classes and re-enable the search
									function endBuild(){
									
										// Show the close tag
										$close = $('<a/>',{
											'id':		'search_close',
											'href':		'#',
											'title':	'Click here to close',
											'html':		'<span class="brand_accent">Close</span>'
										}).appendTo($results).click(function(e){
											
											$overlay.click();
											
											e.preventDefault();
											
										});
										
										cHeight = $close.innerHeight();
										
										$results.css({
											'padding-bottom':	cHeight + 10
										});
										
										$close.css({
											'bottom':		cHeight + 10,
											'margin-left':	Math.round( 0 - $close.width() / 2 )
										}).animate({
											'bottom':	20
										},600,'easeInOutExpo').hover(function(){
										
											if( !searchBan ){
											
												$(this).stop([]).animate({
													'bottom': 10
												},400,'easeInOutExpo');
											
											}
											
										},function(){
											
											if( !searchBan ){
											
												$(this).stop([]).animate({
													'bottom': 20
												},400,'easeInOutExpo');
											
											}
											
										});
										
										
										// Allow another search
										searchBan = false;
										
										// We have a result
										result = true;
										error = false;
										
										// And a bar
										bar = true;
										
									}
								
								}
		
							}
		
						});
					
					}
	
					e.preventDefault();
					
				});
	
				// Set up the overlay to hide everything if clicked
				$overlay.click(function(){
	
					if( !searchBan ){
					
						searchBan = true;
					
						if( result ){
					
							hideResults(function(){
							
								cleanup();
								
							});
						
						}else if( error ){
						
							message('hide',function(){
								
								cleanup();
								
							});
						
						}
					
					}
					
				});
				
				
				//////////////////////////
				// HIDE THE RESULTS
				
				function hideResults(callback){
				
					if( fancy3d ){
				
						//////////////////////////
						// 3D VERSION
				
						// Set up a count
						var i = 0;
						
						// Invert the delays
						$results.find('.flip').each(function(){
						
							$(this).css({
								'-webkit-animation-delay': ( ( total - i ) * o.delayOut ) + 's'
							});
						
							i++;
							
							if( i == total ){
							
								i = 0;
								
								$results.find('.flip:first-child').bind({
									'webkitAnimationEnd':	function(){
									
										// The listener detects all child animations as well, so we have to wait till the end
										i++;
										
										// The end?
										if( i == total ){
										
											// Unbind the listener and get rid of it
											$(this).unbind('webkitAnimationEnd').remove();
											
											// All gone
											$results.removeClass('rollup');
											
											// No more results
											result = false;
											
											// Fire the callback! BOOM!
											if( callback ) callback.apply($results);
										
										}
										
									}
								});
								
								removeClose(function(){
								
									// Start animation
									$results.removeClass('active').addClass('rollup');	
									
								});
								
							}
					
						});
					
					}else{
					
						//////////////////////////
						// NON 3D VERSION
						
						removeClose(function(){
						
							$wrapper.animate({
								'height':	0
							},600,'easeInOutExpo',function(){
							
								$wrapper.remove();
							
								// No more results
								result = false;
								
								// Fire the callback! BOOM!
								if( callback ) callback.apply($results);
							
							});
							
						});
						
					}
					
					function removeClose(callback){
					
						// Hide the close tag
						$close.stop([]).animate({
							'bottom': cHeight + 10
						},400,'easeInBack',function(){
						
							$close.remove();
						
							if( callback ) callback.apply($close);
						
						});
						
					}
				
				}
				
				
				//////////////////////////
				// MESSAGES
				
				function message(title,content,eg,callback){
				
					// Hide the loading spinner
					$loading.fadeOut(200);
					
					// If there is a message, we need to hide it first
					if( error ){
	
						// Remove any existing messages
						$message.animate({
							'margin-top':	0 - $message.outerHeight(),
							'opacity':		0
						},300,'easeInExpo',function(){
						
							// Get rid
							$message.remove();
						
							if( title != 'hide' ){
								
								build();
								
							}else{
							
								// No more errors
								error = false;
							
								// Callback
								if( content ) content.apply($message);
							
							}
						
						});
					
					}else if( result ){
					
						hideResults(function(){
						
							if( title != 'hide' ) build();
							
							// Hide the bar if needed
							if( bar ) hideBar();
							
						});
					
					}else{
					
						if( title != 'hide' ) build();
					
					}
					
					// Hide the bar if needed
					if( bar && !result ) hideBar();
					
					function build(){
					
						// Build the HTML
						var html = '';
						
						// If the content exists, add it to the HTML
						if( title ) html += '<h3>' + title + '</h3><a href="#" class="button"><span>Close</span></a>';
						if( content ) html += '<p class="intro">' + content.replace('!','!</p><p>') + '</p>';
						
						// Do we need the eg list?
						if( eg ) html += '<ul><li>A full UK postcode</li><li>A town, city or village in the UK</li><li>A famous landmark (e.g: Nelsons Column)</li></ul>';
					
						// Build the message and show it
						$message = $('<div/>',{
							'id':		'search_message',
							'class':	'paper shadow',
							'html':		html
						}).appendTo('body').show().css({
							'opacity':		0
						});
						
						// Close button
						$message.find('.button').click(function(){
							$overlay.click();
							return false;
						});
						
						// Now show it (can't do it all in one go as we can't get metrics from an object unless it's been created!
						$message.animate({
							'margin-top':	0 - Math.round( $message.outerHeight() / 2 ),
							'opacity':		1
						},600,'easeOutExpo',function(){
						
							// Allow another search
							searchBan = false;
							
							// We have error!
							error = true;
							result = false;
						
							// Callback
							if( callback ) callback.apply($message);
							
						});
						
					}
				
				}
				
				
				//////////////////////////
				// HIDE THE BAR
				
				function hideBar(callback){
				
					$bar.animate({
						'width':	$form.outerWidth()
					},400,'easeInOutExpo',function(){
					
						$bar.animate({
							'height':	0
						},50,'easeInOutExpo',function(){
							
							// Reset the bar
							$bar.removeAttr('style');
							
							// No more bar
							bar = false;
							
							if( callback ) callback.apply($bar);
						
						});
					});
				
				}
				
				
				//////////////////////////
				// CLEANUP TIME
				
				function cleanup(){
				
					$form.removeClass('active');
					$input.val('');
				
					// Hide the decorative bar thingy if needed
					if( bar ){
					
						hideBar(function(){
								
							// Hide the results div
							$results.hide();
							
							hideOverlay();
	
						});
					
					}else{
					
						hideOverlay();
						
					}
					
					function hideOverlay(){
					
						// Fade out the overlay
						$overlay.fadeOut(200,function(){
						
							// Allow another search
							searchBan = false;
							
						});
					
					}
					
				}
				
			}
			
			activateSearch();

		});		
		
		//////////////////////////
		// CHECK FOR 3D
		// Thanks to http://www.modernizr.com/
		
		function supports3d() {
			// borrowed from modernizr
			var div = document.createElement('div'),
				ret = false,
				properties = ['perspectiveProperty', 'WebkitPerspective'];
			for (var i = properties.length - 1; i >= 0; i--){
				ret = ret ? ret : div.style[properties[i]] != undefined;
			};
		    
		    // webkit has 3d transforms disabled for chrome, though
		    //   it works fine in safari on leopard and snow leopard
		    // as a result, it 'recognizes' the syntax and throws a false positive
		    // thus we must do a more thorough check:
		    if (ret){
		        var st = document.createElement('style');
		        // webkit allows this media query to succeed only if the feature is enabled.    
		        // "@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){#modernizr{height:3px}}"
		        st.textContent = '@media (-webkit-transform-3d){#test3d{height:3px}}';
		        document.getElementsByTagName('head')[0].appendChild(st);
		        div.id = 'test3d';
		        document.body.appendChild(div);
		        
		        ret = div.offsetHeight === 3;
		        
		        st.parentNode.removeChild(st);
		        div.parentNode.removeChild(div);
		    }
		    return ret;
		}
		
	}
		
})(jQuery);
