var SearchBar = function(container){
	this.initialize(container);
}

$.extend(SearchBar, {
	log: function(){
		if(this.debug && console) {
			if(arguments.length == 1){
				console.log(arguments[0]);
			} else if(arguments.length > 1) {
				var output = [];
				$(arguments).each(function(){
					output[output.length] = this;
				});
				console.log(output);
			}
		}
	}
});

$.extend(SearchBar.prototype, {

	// Constructor
	initialize: function(container){
		var searchBar        = this;
		this.container       = container;
		this.form            = $(container).find('form').get(0);
		this.query           = $(container).find('#query').get(0);
		this.ll              = $(container).find('#ll').get(0);
		this.searchLocation  = $(container).find('#search_location').get(0);

		$([this.Geocoder, this.Map, this.Location]).each(function(){
			this.searchBar = searchBar;
		});

		this.Location.load();
		this.elementBehaviors.apply(this);
	},
	
	// Behaviors for elements
	elementBehaviors: {

		// Apply behaviors
		apply: function(searchBar){
			this.query(searchBar);
			this.searchLocation(searchBar);
			this.formSubmit(searchBar);
		},

		// Query input
		query: function(searchBar){
			// Add hint
			if($(searchBar.query).val() == '') {
				$(searchBar.query).val("Søk etter håndverker på navn eller bransje").addClass("hint");
			}
			// Remove hint on focus
			$(searchBar.query).focus(function(){
				$(this).select();
				if($(this).hasClass("hint")){ 
					$(this).val('').removeClass('hint')
				}
			});
			// Clear hint on submit
			$(searchBar.form).submit(function(){
				if($(searchBar.query).hasClass('hint')){
					$(searchBar.query).removeClass('hint').val('');
				}
			});
		},

		// Location input
		searchLocation: function(searchBar){
			
			// Reset method
			$.extend(searchBar.searchLocation, {
				getLocation: function(){
					$(this).val(searchBar.Location.text);
				}
			});
			
			// Show geocoder on focus
			$(searchBar.searchLocation).focus(function(){
				setTimeout(function(){
					$(searchBar.searchLocation).select();
				}, 10);
				searchBar.Geocoder.show('Søk etter stedsnavn, eller <a href="#" class="maplink">Vis kart</a>.');
			});

			// ..and hide on blur
			$(searchBar.searchLocation).blur(function(){
				searchBar.Geocoder.hide();
			});

			// Listen for keyboard events
			$(searchBar.searchLocation).keydown(function(event){
				if(event.which == 40){
					searchBar.Geocoder.nextTarget();
					return false;
				} else if(event.which == 38){
					searchBar.Geocoder.previousTarget();
					return false;
				} else if(event.which == 13){
					// Enter pressed, search immediately.
					// if(this.keyboardSearch){
					// 	if(this.keypressInterval){
					// 		clearInterval(this.keypressInterval);
					// 	}
					// 	if(this.searchBar.geocoder.inProgress){
					// 	}
					// 	searchBar.Geocoder.geocode($(this).val());
					// }
				} else if(!event.metaKey) {
					this.keyboardSearch = true;
					searchBar.Geocoder.inProgress = true;
					searchBar.Geocoder.show('Søker...', {maplink: false});
					if(this.keypressInterval){
						clearInterval(this.keypressInterval);
					}
					this.keypressInterval = setInterval(function(){
						if(searchBar.searchLocation.previousValue != $(searchBar.searchLocation).val()){
							searchBar.searchLocation.previousValue = $(searchBar.searchLocation).val();
							searchBar.Geocoder.geocode($(searchBar.searchLocation).val());
						}
						clearInterval(searchBar.searchLocation.keypressInterval);
					}, 300);
				}
			});
			$(searchBar.Location).bind('change', function(){
				if(this.text){
					searchBar.searchLocation.getLocation();
				}
				searchBar.searchLocation.keyboardSearch = false;
			});
		},

		formSubmit: function(searchBar){
			$(searchBar.Location).bind('change', function(){
				var lat = false;
				var lng = false;
				if(searchBar.Location.latLng) {
					lat = searchBar.Location.latLng.lat();
					lng = searchBar.Location.latLng.lng();
				}
				if(lat && lng) {
					$(searchBar.form).find('#ll').val([lat, lng].join(','));
				} else {
					$(searchBar.form).find('#ll').val('');
				}
			});
			$(searchBar.form).submit(function(){
				if(searchBar.searchLocation.keyboardSearch){
					searchBar.Geocoder.submitCurrentResult(this);
					return false;
				} else {
					return true;
				}
			});
		}
	},
	
	// Geocoder
	Geocoder: {
		address:       false,
		initialized:   false,
		cache:         [],
		results:       false,
		inProgress:    false,
		shown:         false,
		container:     false,
		
		// Initialize the geocoder and bind events.
		initialize: function(){
			if(!this.initialized){
				$(this).bind('ready', function(){
					this.show();
				});
				this.initialized = true;
			}
		},

		// Bounds for the geocoder.
		bounds: function(){
			var sw = new google.maps.LatLng(57.326521, 3.339844);
			var ne = new google.maps.LatLng(81.120388, 35.683594);
			return(new google.maps.LatLngBounds(sw, ne));
		},
		
		// Geocodes an address
		geocode: function(address){
			var geocoder = this;

			geocoder.initialize();
			geocoder.address    = address;
			geocoder.inProgress = true;
			geocoder.results    = false;

			if(geocoder.cache[address]){
				// Results are cached, no request necessary
				geocoder.results    = geocoder.cache[address];
				SearchBar.log('SearchBar: Geocoded "'+address+'", '+geocoder.results.length+' results [cached]');
				geocoder.inProgress = false;
				$(geocoder).trigger('ready');
			} else {
				var gmapsCoder = new google.maps.Geocoder();
				var queryAddress = address + " norway";
				var geocoderOptions = {address: queryAddress, bounds: geocoder.bounds(), language: 'no'};
				if(geocoder.searchBar.Location.latLng){
					geocoderOptions.latLng = geocoder.searchBar.Location.latLng;
				}
				gmapsCoder.geocode(geocoderOptions, function(results, status){
					if (status == google.maps.GeocoderStatus.OK) {
						var selectedResults = [];
						var locationStrings = [];
						for(var a = 0; a < results.length; a++){
							// Only add addresses in Norway
							if(results[a].formatted_address.match(/(Norge|Svalbard|Jan Mayen)$/)){
								// ..which are unique
								if($.inArray(results[a].formatted_address, locationStrings) == -1){
									selectedResults[selectedResults.length] = results[a];
									locationStrings[locationStrings.length] = results[a].formatted_address;
								}
							}
						}
						geocoder.cache[address] = selectedResults;
						if(selectedResults.length > 0){
							geocoder.results = selectedResults;
							SearchBar.log('SearchBar: Geocoded "'+address+'", '+geocoder.results.length+' results');
						} else {
							geocoder.results = false;
							SearchBar.log('SearchBar: Geocoded "'+address+'", no results');
						}
					}
					geocoder.inProgress = false;
					$(geocoder).trigger('ready');
				});
			}

		}, 
		
		// Hide the results
		hide: function(){
			if(this.shown){
				if(this.container){
					$(this.container).fadeOut(200);
				}
				this.shown = false;
			}
		},
		
		// Show the results
		show: function(message, options){
			var geocoder = this;
			
			if(!options){options = {};}
			options = $.extend({maplink: true}, options);
			
			// Create container if necessary
			if(!this.container){
				$(document.body).append('<div id="search_location_results" class="autocomplete"></div>');
				this.container = $('#search_location_results').get(0);
			}
			
			// Position container
			var offsetTop = $('.search_bar #search_location').offset().top + $('.search_bar #search_location').height() + 23;
			var offsetLeft = $('.search_bar #search_location').offset().left + 1;
			$(this.container).css({
				position: 'absolute',
				top:      offsetTop+'px',
				left:     offsetLeft+'px'
			});

			// Draw list
			if(message) {
				$(this.container).html('<p>'+message+'</p>');
			} else if(this.results && this.results.length > 0){
				$(this.container).html('<p>Velg sted under, eller <a href="#" class="maplink">bruk kartet</a>.</p><ul class="results"></ul>');
				var result       = false;
				var resultLink   = false;
				for(var a = 0; a < this.results.length; a++){
					result = this.results[a];
					$(this.container).find('ul').append('<li><a href="#">'+result.formatted_address.replace(/, Norge$/g, '').replace(/^Norge$/, 'Hele landet')+'</a></li>');
					resultLink = $(this.container).find('a:last').get(0);
					resultLink.result = result;
					resultLink.geocoder = geocoder;
					$(resultLink).hover(function(){
						this.geocoder.setTarget(this);
					});
					resultLink.setLocation = function(){
						if($(this).text() == "Hele landet"){
							geocoder.searchBar.Location.update(false, {text: 'Hele landet'});
							// TODO: Make this work
							//console.log('Hele landet');
							// userLocation.locationDisabled = true;
							// userLocation.hideLocationDialog();
							// $(userLocation).trigger('change');
						} else {
							geocoder.searchBar.Location.update(this.result.geometry.location, {text: $(this).text()});
						}
						geocoder.hide();
						return false;
					}
					$(resultLink).click(function(){
						this.setLocation();
					});
				}
			} else {
				$(this.container).html('<p class="no_results">Finner desverre ikke noe sted som heter <strong>'+this.address+'</strong>.<br /><a href="#" class="maplink">Vil du heller bruke kartet?</a></p>');
			}

			$(this.container).find('a.maplink').click(function(){
				geocoder.hide();
				geocoder.searchBar.searchLocation.getLocation();
				geocoder.searchBar.Map.show();
				return false;
			});

			// Animate appearance
			if(!this.shown){
				$(this.container).fadeIn(500);
				this.shown = true;
			}

		},
		
		nextTarget: function(){
			if(this.container && $(this.container).find('.results a').length > 0) {
				var results = $(this.container).find('.results a');
				var currentTarget = this.getTarget();
				var index = -1;
				if(currentTarget) {
					index = results.index(currentTarget) + 1;
				} else {
					index = 0;
				}
				if(index >= results.length){
					index = 0;
				}
				this.setTarget(results.get(index));
			}
		},
		
		previousTarget: function(){
			if(this.container && $(this.container).find('.results a').length > 0) {
				var results = $(this.container).find('.results a');
				var currentTarget = this.getTarget();
				var index = -1;
				if(currentTarget) {
					index = results.index(currentTarget) - 1;
				} else {
					index = (results.length - 1);
				}
				if(index < 0){
					index = (results.length - 1);
				}
				this.setTarget(results.get(index));
			}
		},

		getTarget: function(){
			if(this.container && $(this.container).find('.results a').length > 0) {
				var currentResult = $(this.container).find('.results .targeted');
				if(currentResult.length > 0){
					return currentResult.get(0);
				} else {
					return false;
				}
			}
		},

		setTarget: function(link){
			if(this.container && $(this.container).find('.results a').length > 0) {
				$(this.container).find('.results a').removeClass('targeted');
				$(link).addClass('targeted');
			}
		},
		
		submitCurrentResult: function(form){
			var geocoder = this;
			if(this.inProgress){
				setTimeout(function(){geocoder.submitCurrentResult();}, 20);
			} else {
				if(this.container && $(this.container).find('.results a').length > 0) {
					if(!this.getTarget()){
						this.setTarget($(this.container).find('.results a').get(0));
					}
					this.getTarget().setLocation();
					geocoder.searchBar.searchLocation.keyboardSearch = false;
					setTimeout(function(){$(form).submit()}, 20); // Delayed submit
				} else {
					geocoder.show();
				}
			}
		}
	},

	Location: {
		loaded:      false,
		ipLookup:    false,
		latLng:      false,
		text:        false,
		
		// Load location from backend via JSON
		load: function(){
			var location  = this;
			location.text = false;
			var llString = $(this.searchBar.ll).val();
			var searchLocationString = $(this.searchBar.searchLocation).val();
			if(llString){
				var ll = llString.split(',');
				location.latLng = new google.maps.LatLng(parseFloat(ll[0]), parseFloat(ll[1]));
				location.text = $(this.searchBar.searchLocation).val();
				location.loaded   = true;
				location.ipLookup = false;
				if(location.text){
					$(location).trigger('ready');
				} else {
					this.save();
				}
			} else if(!searchLocationString.match(/^hele landet$/i)){
				// Load from Ajax
				$.getJSON("/location.json", function(json) {
					SearchBar.log('SearchBar: Loaded location from JSON');
					location.loaded = true;
					location.setFromJSON(json);
					$(location).trigger('ready');
				});
			}
		},
		
		// Save location to backend
		save: function(){
			var location  = this;
			var data = {lat: this.latLng.lat(), lng: this.latLng.lng(), authenticity_token: AUTH_TOKEN};
			$.put('/location.json', data, function(json){
				location.setFromJSON(json);
			}, "json");
		},
		
		// Update the location. Triggers 'change' immediately if text is set.
		update: function(latLng, options){
			if(!options){options = {};}
			this.latLng = latLng;
			if(options.text){
				this.text = options.text;
				$(this).trigger('change');
			} else {
				this.text = false;
			}
			SearchBar.log('SearchBar: Updated location: "'+this.text+'"');
			if(this.latLng){
				this.save();
			}
		},
		
		// Set data from JSON
		setFromJSON: function(json, options){
			this.ipLookup = json.detected;
			this.latLng   = new google.maps.LatLng(parseFloat(json.lat), parseFloat(json.lng));
			if(!this.text){
				if (json.city) {
					this.text = json.city;
				} else if(json.state) {
					this.text = json.state + ' fylke';
				} else {
					this.text = json.full_address;
				}
				$(this).trigger('change');
			}
		}
	},
	
	// Map
	Map: {
		initialized: false,
		shown:       false,
		container:   false,
		gmap:        false,
		userMarker:  false,
		
		initialize: function(){
			if(!this.initialized){
				var map = this;
				// Update positions on location change
				$(this.searchBar.Location).bind('change', function(){
					if(map.gmap && map.userMarker && this.latLng){
						map.gmap.set_center(this.latLng);
						map.userMarker.setPosition(this.latLng);
					}
				});
				this.initialized = true;
			}
		},
		
		hide: function(){
			if(this.shown){
				this.shown = false;
				$('#change_location_fadeout').hide();
				$(this.container).html('').hide();
			}
		},
		
		show: function(){
			var map = this;
			map.initialize();
			if(!this.searchBar.Location.loaded){
				setTimeout(function(){map.show();}, 50); // Retry until location is available.
			} else if(!this.shown) {

				// Create container if necessary
				if(!this.container){
					$(document.body).append('<div id="change_location"></div>');
					this.container = $('#change_location').get(0);
				}

				// Redraw and center
				$(this.container).html('<div class="map"></div><a class="close">Ok</a>"');
				var offsetX = Math.floor($(document).width() / 2) - ($(this.container).width() / 2);
				if(offsetX < 0) {offsetX = 0;}
				$(this.container).css('left', offsetX + 'px').show();

				// Create the map
				$(this.container).find('div.map').each(function(){

					// Stupid workaround for stupid browsers
					if(!$(this).width()){
						$(this).width('940').height('460');
					}

					var location = map.searchBar.Location;

					// Create map
					map.gmap = new google.maps.Map(this, {
						center:    location.latLng, 
						zoom:      10,
						mapTypeId: google.maps.MapTypeId.ROADMAP
					});
					
					// Marker: Create
					map.userMarker = new google.maps.Marker({
						position: location.latLng, map: map.gmap, draggable: true, visible: true
					});
					// Marker: Center on click
					google.maps.event.addListener(map.userMarker, 'click', function() {
						map.gmap.set_center(map.userMarker.position);
					});
					// Marker: Update location on drag
					google.maps.event.addListener(map.userMarker, 'dragend', function() {
						location.update(map.userMarker.position);
					});
				});

				// Fadeout
				if($('#change_location_fadeout').length < 1) {
					$(document.body).append('<div id="change_location_fadeout"></div>');
					$('#change_location_fadeout').click(function(){
						map.hide();
					});
				}
				$('#change_location .close').click(function(){
					map.hide();
				});
				var fadeout = $('#change_location_fadeout').get(0);
				$(fadeout).show().css({
					position: 'absolute', top: 0, left: 0, width: $(document).width()+'px', height: $(document).height()+'px', 'z-index': 9,
					'background-color': '#000000', opacity: 0
				}).animate({
				 	opacity: 0.6
				}, 300);

				this.shown = true;
			}
		}
	}
	
});

// Detect search bar
$('.search_bar').onDetect(function(){
	this.searchBar = new SearchBar(this);
	$(this.searchBar.Location).bind('ready', function(){
		$('#searched_location').html(this.text);
	});
});

















// ---------- OLD CODE -------------------

// Search bar logic
/*
$('.search_bar').onDetect(function(){
	var searchBar = this;
	var keyboardSearch = false;

	var locationSearch = $(searchBar).find('#search_location').get(0);

	$(GodtJobba.userLocation).bind('ready', function(){
		var locationObject = this;

		$(locationSearch).focus(function(){
			//locationObject.showLocationDialog();
			setTimeout(function(){
				$(locationSearch).select();
			}, 100);
		});
		$(searchBar).find('#query').focus(function(){
			locationObject.hideLocationDialog();
		});


		// $(searchBar).find('input[name=use_location]').change(function(){
		// 	var useLocation = $(searchBar).find('input[name=use_location]:checked').val();
		// 	if(useLocation && useLocation != 'false') {
		// 		$(searchBar).find('.location').val(locationObject.latLng().join(','));
		// 	} else {
		// 		$(searchBar).find('.location').val('');
		// 	}
		// });
		// $(searchBar).find('.user_location_button').show();
		// $(searchBar).find('.change_user_location').click(function(){
		// 	locationObject.changeLocationDialog();
		// });
	});

	$(GodtJobba.userLocation).bind('change', function(){
		keyboardSearch = false;
		if(this.locationDisabled){
			$(locationSearch).val('Hele landet');
			$(searchBar).find('.location').val('');
		} else {
			if($(locationSearch).val() != this.locationText()){
				$(locationSearch).val(this.locationText());
			}
			$(searchBar).find('.location').val(this.latLng().join(','));
		}
	});
	
	// Submit hook
	$(searchBar).find('form').submit(function(){
		if(keyboardSearch){
			if(GodtJobba.userLocation.geocoding){
				$(GodtJobba.userLocation).bind('done_geocoding', function(){
					console.log('hi mom');
				});
			}
			return false;
		}
		return true;
	});
	
	//GodtJobba.userLocation.load();
});
*/





