var map;

var currentLatitude;
var currentLongitude;
var currentZoom;

var searchField;

var infoWindowSticky = false;

var storeMarkers = {};

var distanceForZoomFactor = {
	19: 1,
	18: 1,
	17: 1,
	16: 1,
	15: 1,
	14: 2,
	13: 3,
	12: 6,
	11: 12,
	10: 24,
	 9: 40,
	 8: 80,
	 7: 150,
	 6: 300,
	 5: 300,
	 4: 300,
	 3: 300,
	 2: 300,
	 1: 300
}

var minZoom = 7;
var webshopZoom = 5;

var interactionLock = false;

var trackingEnabled = false;

var baseTitle = "";

google.load("maps", "2");

$(document).ready(function( ) {
	trackingEnabled = window["SWFAddress"] != null && window["pageTracker"] != null;
	baseTitle       = trackingEnabled ? SWFAddress.getTitle() : "";
	
	map = new google.maps.Map2(document.getElementById("storefinder-map"));
	map.addControl(new google.maps.SmallMapControl());
	//map.addControl(new google.maps.MapTypeControl());
	
	createSearchUI();
	
	var position = new google.maps.LatLng(57.717, 11.967); // Nudie HQ
	
	if ( google.loader.ClientLocation ) {
		position = new google.maps.LatLng(google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude);
	} else {
		errorMessage("Cannot determine your location, using Nudie HQ instead.");
	}
	
	map.setCenter(position, 13);
	
	google.maps.Event.addListener(map, "dragend", mapDragged);
	google.maps.Event.addListener(map, "zoomend", mapZoomed);

	if ( trackingEnabled ) {
		// put the query from the URL into the search field, if there is one
		
		var path = SWFAddress.getValue().replace('_', '%');
		
		if ( /^\/query\/(.*)$/.test(path) ) {
			searchField.val(unescape(RegExp.$1));
		} else if ( /^\/storefinder\/store\/(\d+)/.test(path) ) {
      searchField.val(unescape("store-" + RegExp.$1));
		}
	}

	if ( isSearch() ) {
		loadStoresForQuery();
	} else {
		loadStoresForMap();
	}
});

var mapDragged = function( ) {
	if ( ! interactionLock ) {
		trackEvent("drag");
	
		resetSearch();
	
		loadStoresForMap();
	}
}

var mapZoomed = function( ) {
	if ( ! interactionLock ) {
		trackEvent("zoom", null, map.getZoom())
	
		if ( map.getZoom() < minZoom ) {
			map.zoomIn();
		} else {
			resetSearch();
	
			loadStoresForMap();
		}
	}
}

var resetSearch = function( ) {
	searchField.val("");
	
	loadStoresForMap();
}

var isSearch = function( ) {
	return ( ! /^\s*$/.test(getQuery()) );
}

var isSingleStoreSearch = function( ) {
	return isSearch() && getQuery().indexOf("#") == 0;
}

var getQuery = function( ) {
	return searchField.val()
}

var search = function( ) {
	if ( isSearch() ) {
		trackEvent("search", getQuery());
		
		interactionLock = true;
		
		map.setZoom(13);
		
		interactionLock = false;
		
		clearStores();
		
		loadStoresForQuery();
	}
}

var createSearchUI = function( ) {
	searchField = $('<input type="text"/>');
	
	// set default value
	searchField.val(QUERY);
	
	var form            = $("<div></div>");
	//var clearButton     = $('<a>Clear</a>');
	var searchButton    = $('<a>Search&nbsp;&raquo;</a>');
	var buttonContainer = $('<span></span>');
	
	//buttonContainer.append(clearButton);
	//buttonContainer.append('&nbsp;/&nbsp;');
	buttonContainer.append(searchButton);
		
	form.append(searchField);
	form.append("&nbsp;");
	form.append(buttonContainer);
	
	searchField.keypress(function( e ) {
		if ( e.which == 10 || e.which == 13 ) {
			e.preventDefault();
			e.stopPropagation();
			
			search();
		}
	});
	
	//clearButton.click(function( ) {
	//	resetSearch();
	//});

	searchButton.click(function( ) {
		search();
	});
	
	$("#search-ui").append(form);
	
	searchField.width(form.width() - buttonContainer.width() - 15);
}

var fixStoresListUI = function( ) {
	var siblingHeights = 0;
	
	$("#stores").children().each(function( ) {
		if ( this.id != "stores-list" ) {
			siblingHeights += $(this).height();
		}
	});
	
	$("#stores-list").height($("#stores").height() - siblingHeights - 16);
}

var loadStoresForQuery = function( ) {
	trackPage('query/' + escape(getQuery()), "\"" + getQuery() + "\"");
	
	loadStores(STORES_URL + "?query=" + escape(getQuery()));
}

var loadStoresForMap = function( ) {
	var zoom = map.getZoom();
	
	if ( zoom >= minZoom ) {
		var center = map.getCenter();
	
		var longitude = center.lng().toString().replace(/^\s*(\d+\.\d{3}).*$/, "$1");
		var latitude  = center.lat().toString().replace(/^\s*(\d+\.\d{3}).*$/, "$1");
	
	
		if ( currentLatitude != latitude || currentLongitude != longitude || currentZoom != zoom ) {
			var url = STORES_URL + "?latitude=" + latitude + "&longitude=" + longitude + "&distance=" + distanceForZoomFactor[zoom];
	
			loadStores(url);
		
			currentLongitude = longitude;
			currentLatitude  = latitude;
			currentZoom      = zoom;
		}
	}
}

var loadStores = function( url ) {	
	$.getJSON(url, placeStores);

	message("Loading stores...");
	
	fixStoresListUI();
}

var clearStores = function( ) {
	$("#stores-list").empty();
}

var placeStores = function( stores ) {
	var storesList = $("#stores-list").empty();
	
	if ( stores == null || stores.length == 0 ) {
		if ( isSearch() ) {
			message("Could not find any stores, try again with another query.");
		} else {
			message("There are no stores within " + distanceForZoomFactor[map.getZoom()] + " km of the center of the map, try searching or zooming out.");
		}
		
		fixStoresListUI();
	} else {
		if ( isSingleStoreSearch() ) {
			message("");
		} else if ( isSearch() ) {
			message("Found " + stores.length + " stores for the query \"" + getQuery() + "\"");
		} else {
			message("There are " + stores.length + " stores within " + distanceForZoomFactor[map.getZoom()] + " km of the center of the map.");
		}
		
		fixStoresListUI();
		
		stores.sort(function( a, b ) {
			return a.name == b.name ? 0 : a.name > b.name ? 1 : -1;
		});
		
		var maxLng = stores[0].longitude;
		var minLng = stores[0].longitude;
		var maxLat = stores[0].latitude;
		var minLat = stores[0].latitude;
	
		$(stores).each(function( ) {
			maxLng = Math.max(maxLng, this.longitude);
			minLng = Math.min(minLng, this.longitude);
			maxLat = Math.max(maxLat, this.latitude);
			minLat = Math.min(minLat, this.latitude);
		
			storesList.append(storeToHtml(this, true));

			if ( this.internetonly != 1 ) {
				//var markerIcon = new google.maps.Icon(G_DEFAULT_ICON);
				//
				//markerIcon.image    = baseUrl + "/static/images/n-icon.png";
				//markerIcon.iconSize = new google.maps.Size(16, 16);
				//		
				//var markerOptions = {icon: markerIcon};
		
				var markerOptions = { };

				if ( storeMarkers[this.storeId] == null ) {
					var point = new google.maps.LatLng(this.latitude, this.longitude);

					var store = this;

					var marker = new google.maps.Marker(point, markerOptions);
			
					google.maps.Event.addListener(marker, "click", function( ) {
						activateStore(store, true);
					});

					map.addOverlay(marker);
			
					storeMarkers[this.storeId] = marker;
				}
			}
		});
		
		var distance = Math.max(Math.abs(maxLat - minLat), Math.abs(maxLng - minLng));
		var zoom     = distance > 100 ? 6 : 13;

		// TODO: zoom to an appropriate level based on the distance
		
		interactionLock = true;
	
		if ( isSearch() ) {
			if ( stores.length == 1 && stores[0].internetonly == 1 ) {
				var position = new google.maps.LatLng(stores[0].latitude, stores[0].longitude);

				map.setCenter(position, webshopZoom);
			} else if ( stores.length > 0 ) {
				// center on first store
		
				var center   = map.getCenter();
				var position = new google.maps.LatLng(stores[0].latitude, stores[0].longitude);
		
				var latDiff = Math.abs(center.lat() - position.lat());
				var lngDiff = Math.abs(center.lng() - position.lng());
		
				if ( latDiff > 0.01 && lngDiff > 0.01 ) {
					map.setCenter(position, map.getZoom());
				}
			}
		}
		
		interactionLock = false;
	}
}

var storeToHtml = function( store, clickable ) {
	var storeNode = $('<div class="store"></div>');
	
	var name = store.name;
	
	if ( store.internetonly == 1 ) {
		name += " <span class=\"webshop\">(web shop)</span>";
	}
	
	var nameNode = $('<h3>' + name + '</h3>');
	
	storeNode.append(nameNode);
	
	if ( store.internetonly != 1 ) {
		storeNode.append('<div>' + getAddress(store) + '</div>');
	
		if ( store.phone != null && store.phone.length > 0 ) {
			storeNode.append('<div>' + store.phone + '</div>');
		}
	}
	
	if ( store.url != null && store.url.length > 0 ) {
		storeNode.append('<div><a href="http://' + store.url + '">' + store.url + '</a></div>');
	}
	
	if ( clickable ) {
		storeNode.click(function( ) { activateStore(store, true); });
		storeNode.css("cursor", "crosshair");
		
		storeNode.hover(
			function( ) {
				store.hoverTimeout = setTimeout(function( ) {
					clearTimeout(store.hoverTimeout);
					
					activateStore(store);
				}, 500);
			},
			function( ) {
				clearTimeout(store.hoverTimeout);
				
				deactivateStore(store);
			}
		);
	}
	
	return storeNode;
}

var getAddress = function( store ) {
	var str = store.address;
	
	str += ', ' + store.city;

	if ( store.areaName != null && store.areaName.length > 0 ) {
		str += ', ' + store.areaName;
	}
	
	str += ', ' + store.country;
	
	return str;
}

var activateStore = function( store, sticky ) {
	if ( sticky ) {
		trackPage("/storefinder/store/" + store.storeId, store.name);
		trackEvent("showStore", store.storeId);
	}
	
	var marker = storeMarkers[store.storeId];
	
	marker.openInfoWindowHtml(storeToHtml(store, false).html());
	
	map.setCenter(marker.getLatLng());
	
	infoWindowSticky = sticky;
}

var deactivateStore = function( store ) {
	if ( ! infoWindowSticky ) {
		map.closeInfoWindow();
	}
}

var errorMessage = function( msg, clear ) {
	if ( clear ) {
		$("#stores-list").empty();
	}
	
	message(msg, true);
}

var message = function( msg, error ) {
	$("#explanation").text(msg);
}

var trackPage = function( url, title ) {
	if ( trackingEnabled ) {
		SWFAddress.setValue(url.replace('%', '_'));
		
		if ( title ) {
			SWFAddress.setTitle(baseTitle + " / " + title);
		} else {
			SWFAddress.setTitle(baseTitle);
		}
	}
}

var trackEvent = function( name, label, value ) {
	if ( trackingEnabled ) {
		pageTracker._trackEvent("storefinder", name, label, value);
	}
}