//------------------------------------
//
//	ENGAGE.LOCATION.JS
//	Author: 	Engage Interactive
//	Requires:	jquery 1.6
//				engage.findmynearest
//	Version:	2
//
//------------------------------------


(function($){

	//////////////////////////
	// GLOBAL VARIABLES
	
	var mooseBan = false;
	var mHover = false;		// Hovering over the popup?
	var nHover = false;		// Hovering over the link?
	var sOpen = false;		// Is the select open?
	var visible = false;
	var shaking = false;
	var timer;
	var locations = new Array();
	var properties;
	
	// For the wording - These are set so that we know whether to change them or not
	var cTitle;
	var cIntro;
	var cUrl;
	
	
	//////////////////////////
	// GLOBAL OBJECTS
	
	var $html = $('html');
	var $this;
	var $lp;
	var $lp_form;
	var $arrow;
	
	
	//////////////////////////
	// BEGIN PLUGIN
	
	jQuery.fn.location = function (settings){

		//////////////////////////
		// DEFAULTS

		var defaults = {
			'title':		'Find your nearest',
			'intro':		'Please choose your nearest location using the form below. You can search using a place name, landmark or postcode.',
			'url':			'/location/[location]',
			'json':			'/locations/json',
			'results':		4,
			'prefix':		'lp_',
			'offset':		20,
			'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);
		
		//////////////////////////
		// CREATE THE POPUP

		if( $('#location_picker').length == 0 ){

			// The main container
			$lp = $('<div/>',{
				'id':		'location_picker',
				'html':		'<h3 id="' + o.prefix + 'title">Title</h3><label for="' + o.prefix + 'search_term" class="intro">Intro</label>'
			});
			
			
			// Build the forms
			$lp_form = $('<form/>',{
				'id':		o.prefix + 'form',
				'html':		'<fieldset id="' + o.prefix + 'search">\
								<span class="join">\
									<input id="' + o.prefix + 'search_term" placeholder="Search">\
									<button type="submit">Go</button>\
								</span>\
								<span id="' + o.prefix + 'loading"></span>\
							</fieldset>\
							<fieldset id="' + o.prefix + 'list"></fieldset>'
			}).appendTo($lp);
			
			
			// Add it to the page and bind some events
			$lp.appendTo('body').bind({
				'mouseenter':	function(){
					
					mHover = true;
					
				},
				'mouseleave':	function(){
					
					mHover = false;
					
					cleanUp();
					
				}
			});
			
			
			// Add in the arrow
			$arrow = $('<span/>',{
				'id':		o.prefix + 'arrow'
			}).appendTo($lp);
			
			// Add in the locations
			$.getJSON(o.json, function(json) {

				locations = json;
				
			});
		
		}
		
		//////////////////////////
		// ACTIVATE SEARCH

		function activateSearch(){
			
			var $error = $('<div/>',{
				'id':	o.prefix + 'error'
			});
				
			var $results = $('<div/>',{
				'id':	o.prefix + 'results'
			});
			
			var error = false;
			var result = false;
			var searchBan = false;
			
			if( visible ){
			
				// Clean up errors
				$('#' + o.prefix + 'error, #' + o.prefix + 'results').animate({
					'opacity':	0
				},200).slideUp(200,'easeInOutExpo',function(){
					$(this).remove();
				});
				
			}else{

				$('#' + o.prefix + 'error, #' + o.prefix + 'results').remove();
			
			}
			
			// And search terms
			$('#' + o.prefix + 'search_term').blur().val('');
			
			// Function to create messages
			var message = function(html){
			
				$results.remove();

				// Do we need to create the error div?
				if( !error ){
				
					$error.html('<div class="alert">' + html + '</div>').appendTo($lp_form).slideDownFadeIn();
					
				}else{
				
					$error.html('<div class="alert">' + html + '</div>').slideDownFadeIn();
					
				}
				
				$lp_form.removeClass('loading');
				
				searchBan = false;
				result = false;
				error = true;
				
			}
			
			// Unbind the previous submit, and apply another so that we use current settings
			$lp_form.unbind('submit').submit(function(e){

				// Disable if in the middle of search or Google Maps not loaded
				if( searchBan || !googleMapsEnabled ) return false;
				
				else searchBan = true;
				
				// Set a delay if we already have a result or an error
				if( error || result ){

					$error.fadeOutSlideUp();
					
					$results.fadeOutSlideUp();
					
					var delay = 350;
					
				}else{
				
					var delay = 0;
				
				}
				
				setTimeout(function(){
					if( searchBan ) $lp_form.addClass('loading');
				},300);
				
				setTimeout(function(){
				
					// Start search
					findMyNearest($('#' + o.prefix + 'search_term').val(), {
						dataSource:		o.json,
						searchTotal:	o.results,
						logger:			false,
						onBlank:		function() {
							message('<h4>Oops&hellip;</h4><p>To find your nearest you need to enter a search term. e.g:</p><ul><li>A full UK postcode</li><li>A UK city, town or village</li><li>UK landmark (e.g. Big Ben)</li></ul>');
						},
						onNoResult:		function() {
							message('<h4>Sorry, no results&hellip;</h4><p>Why not try searching using one of the following:</p><ul><li>A full UK postcode</li><li>A UK city, town or village</li><li>UK landmark (e.g. Big Ben)</li></ul>');
						},
						onLondon:		function() {
							message('<h4>Sorry&hellip;</h4><p>London is a big place, please be a bit more specific. For example; try entering a London suburb such as &lsquo;Islington&rsquo;.</p>');
						},
						onResult:		function(results) {
							
							$error.remove();
							
							var html = '';
							var i = 1;
							
							$lp_form.removeClass('loading');
							
							for(var key in results) {
							
								html += '<li class="result_' + i + '"><a href="' + o.url.replace('[location]',results[key].slug) + '">' + results[key].name + ' <small>' + results[key].distance + ' m</small></a></li>';
								
								i++;
								
							}
							
							// Do we need to create the results container?
							if( !result ){
							
								$results.html('<h4>Search results</h4><ul>' + html + '</ul>').appendTo($lp_form).slideDownFadeIn();
							
							}else{
							
								$results.slideDownFadeIn().find('ul').html(html);
							
							}
							
							// We have a result
							result = true;
							error = false;
							
							// Allow another search
							searchBan = false;
							
						}
					});
				
				},delay);
								
				e.preventDefault();
				
			});
		
		}
		
		// Ready callback
		o.ready.apply($this);

		// For each link
		return this.each(function(){

			var $this = $(this);
			
			// Bind some events
			$this.bind({
				'mouseenter':	function(){
					
					// Set hover
					nHover = true;
					
					// Clear any hide timers
					clearTimeout(timer);
					
					
					//////////////////////////
					// SET CONTENT
					// If it has changed
					
					if( cIntro != o.intro ){
					
						$lp.find('.intro').empty().text(o.intro);
					
					}
					
					if( cTitle != o.title ){
					
						$lp.find('#' + o.prefix + 'title').empty().text(o.title);
						
					}
					
					if( cUrl != o.url ){

						// Remove current select list
						$lp_form.find('.select').remove();
					
						// Start building a new one
						var list = '<option disabled selected>Please select one</option>';
				
						// For each location
						for( var i in locations ) {
							
							list = list + '<option value="' + o.url.replace('[location]',locations[i].slug) + '">' + locations[i].name + '</option>';
		
						}
						
						// Finish building the list
						$('<select/>',{
							'html':	list
						}).appendTo('#lp_list').simpleSelect().bind({
							'change':		function(){
							
								location.href = $(this).val();
								
							},
							'focus':	function(){
								sOpen = true;
							},
							'blur':		function(){
								sOpen = false;
							}
						});
						
						// Update the submit function
						activateSearch();
						
						cUrl = o.url;
					
					}
					
					// Callback for cufon
					if( cIntro != o.intro || cTitle != o.title ){
					
						cIntro = o.intro;
						cTitle = o.title;
					
						o.before.apply($this);
						
					}
					
					
					//////////////////////////
					// POSITIONING
					
					var offset = $this.offset();
					var w = $this.width();
					var h = $this.outerHeight();
					
					// x & y
					var x = Math.round( offset.left + ( w / 2 ) ) - ( $lp.outerWidth(true) / 2 );
					var y = offset.top + h + o.offset;

					// Make sure we stay on the page
					if( x < o.offset ){
					
						x = o.offset;
					
					}else if( ( x + $lp.width() + o.offset ) > $html.width() ){
						
						x = $html.width() - $lp.width() - o.offset - 5;
						
					}
					
					
					// Are we visible? If not, we can set up for fresh animation
					if( !visible ){
						
						properties = {
							marginTop: o.offset,
							left: x,
							top: y
						};
						
						if(!$('html').hasClass('ie')) {
							properties.opacity = 0;
						}
					
						$lp.show().css(properties);
						
						$arrow.css({
							'left':		Math.round( offset.left - x + ( w / 2 ) - ( $arrow.width() / 2 ) )
						});
						
					}
					
					properties = {};
					
					if(!$('html').hasClass('ie')) {
						properties.opacity = 1;
					}
					
					properties.left = x;
					properties.top = y;
					properties.marginTop = 0;
					
					$lp.show().stop([]).animate(properties, 400, 'easeInOutExpo', function(){
						
						visible = true;
						
					});
					
					$arrow.animate({
						'left':		Math.round( offset.left - x + ( w / 2 ) - ( $arrow.width() / 2 ) )
					},400,'easeInOutExpo');
					
				},
				'mouseleave':	function(){
					
					nHover = false;
					
					cleanUp();
					
				},
				'click':		function(e){
				
					// Bring attention to the drop down
					shake();
					
					e.preventDefault();
					
				}
			});
			
		});
		
		// Hide it
		function cleanUp(){
		
			timer = setTimeout(function(){
				
				if( !nHover && !mHover && !sOpen ){
					
					properties = {};
					
					if(!$('html').hasClass('ie')) {
						properties.opacity = 0;
					}
					
					properties.marginTop = o.offset;
					
					$lp.animate(properties, 200, 'easeInOutExpo', function(){
						
						$lp.hide();
						visible = false;
						
					});
					
				}
				
			},300);
			
		}
		
		// Shaking
	
		function shake(){
			
			if( !shaking ){
			
				// Stop people mashing
				shaking = true;
			
				var s = 40;
				var p = {'margin-left': 4};
				var n = {'margin-left': -4};
				
				// Wiggle wiggle
				$lp.animate(p,s).animate(n,s).animate(p,s).animate(n,s).animate(p,s).animate({
					'margin-left':	0
				},s,function(){
					shaking = false;
				});

			}
			
		}
	
	}
	
	jQuery.fn.slideDownFadeIn = function (callback){
	
		return this.each(function(){
			
			if($('html').hasClass('ie7')) {
				
				$(this).hide().show();
				if( callback ) callback.apply($(this));
				
			}
			else {
				
				$(this).hide().slideDown(400,'easeInOutExpo').fadeIn(200,function(){
					if( callback ) callback.apply($(this));
				});
				
			}
		
		});
	
	}
	
	jQuery.fn.fadeOutSlideUp = function (callback){
	
		return this.each(function(){

			$(this).fadeOut(100).slideUp(200,'easeInOutExpo',function(){
				if( callback ) callback.apply($(this));
			});
		
		});
	
	}

})(jQuery);
