var maxStores = 10; // sets the number of stores to be shown on postcode lookup
var maxSeconds = 0; // sets the max duration for postcode lookup
var maxDistance = 0; // sets the max distance for postcode lookup
var buffer = 5; // how many extra store distances should be calculated but not shown on results
				// this is important because some stores could be further away but have a shorter journey time
var directions_list = document.getElementById("map_directions");
var directions2;

// Infowin class for displaying a miniature info window. Does not
// respond to any events - so you should show and remove the
// overlay yourself as necessary.

function Infowin(latlng, html, popupID) {
	this.latlng_ = latlng;
	this.html_ = html;
	this.prototype = new GOverlay();
	var that = this;
	
	// Creates the DIV representing the infowindow
	this.initialize = function(map) {
		var div = $('<div />');
		div.css({
			position : 'absolute',
			width : 269
		}).appendTo(map.getPane(G_MAP_FLOAT_PANE))
	
		this.map_ = map;
		this.div_ = div;

		this.update(html);
		
		$(div).find(".close").click(function(){
			map.removeOverlay(that);
		});
	}

	this.update = function(html){
		this.html_ = html;
		
		this.div_.empty();
		
		var closebtn = $("<div>").attr("class", "close").html("&nbsp;").css({
			width: 44,
			height: 10,
			background : 'transparent url(/pws/images/img_close.jpg) top left no-repeat',
			position: 'absolute',
			right: 16,
			top: 18,
			cursor: 'pointer',
			'z-index' : '5000'
		});
		
		$('<div />').attr("class", "store_popup_top").css({
			height : 10,
			padding: '0 0 0 0'
		}).append(closebtn).appendTo(this.div_);
		
		var content = $('<div/>').attr("id", "popup_content_" + popupID).addClass('infowin_content').css({
			'position' : 'relative',
			'display': 'inline-block',
			'overflow' : 'hidden',
			'padding' : '10px',
			'max-height' : 380,
			'top' : -5
		}).html(html);
		
		$('<div />').attr("class", "store_popup_bottom").append(content).appendTo(this.div_);
		
		
		var arrow = $('<div />').attr("class", "store_popup_arrow").css({									
			width: 16,
			height : 8,
			padding: '0',
			margin: 'auto'
		});
		
		$('<div />').attr("class", "store_popup_arrow_wrapper").css({
			width: '100%'
		}).append(arrow).appendTo(this.div_);
		
		this.redraw(true);
		//map.setCenter(centerPoint, zoomLevel);
		
	}
	
	// Remove the main DIV from the map pane
	this.remove = function() {
	  this.div_.remove();
	}
	
	// Copy our data to a new instance
	this.copy = function() {
	  return new Infowin(this.latlng_, this.html_);
	}

	// Redraw based on the current projection and zoom level
	this.redraw = function(force) {
		if (!force) return;

		var point = this.map_.fromLatLngToDivPixel(this.latlng_);

		// Now position our DIV based on the DIV coordinates of our bounds
		this.div_.css({
			left : point.x - this.div_.width()/2,
			top : point.y - this.div_.height()
		});
		
	}
	this.recalculateMap = function(){
		var storePoint = this.map_.fromLatLngToDivPixel(this.latlng_);
		var newX = storePoint.x;
		var newY = storePoint.y - parseInt(this.div_.height()/2);
		var newCenterPoint = new GPoint(newX, newY);
		this.map_.panTo(this.map_.fromDivPixelToLatLng(newCenterPoint));
	}
}

function initialisePostcodeInput(store_window){
	$(store_window).find("input.directions_postcode").click(function(){
		$(this).focus();
	});
}

// create a linked list to automatically order the list
function node(d, dirObj, next) {
	
	this.duration = d;
	this.directionsObj = dirObj;
	this.next = next;
}
var linkedList;

// addToList will create an ordered list based on input in seconds
function addToList(previous, current, seconds, directions)
{
	// append journey info here for use later
	if(current == null)
	{
		var newNode = new node(seconds, directions, null);
		if(!(previous == null)){ previous.next = newNode; }
		else{ linkedList = newNode; }
	}
	else if(seconds < current.duration){
		var newNode = new node(seconds, directions, current);
		if(previous){ previous.next = newNode; }
		else{ linkedList = newNode; }
	}
	else{
		//run again with current -> next
		addToList(current, current.next, seconds, directions);
	}
}

function distance_node(d, p, n) {
	this.distance = d;
	this.point = p;
	this.next = n;
}
var calculatedList;
function addToTempList(previous, current, seconds, point)
{
	// append journey info here for use later
	if(current == null)
	{
		var newNode = new distance_node(seconds, point, null);
		if(!(previous == null)){ previous.next = newNode; }
		else{ calculatedList = newNode; }
	}
	else if(seconds < current.distance){
		var newNode = new distance_node(seconds, point, current);
		if(previous){ previous.next = newNode; }
		else{ calculatedList = newNode; }
	}
	else{
		//run again with current -> next
		addToTempList(current, current.next, seconds, point);
	}
}

function updateProgressBar(pointCounter)
{
	var box_width = $("#overlay_progress").width();
	var bar_width = box_width * (pointCounter / maxStores);
	$("#overlay_progress_bar").css("width", bar_width + "px");
}

function displayMapOverlay()
{
	var map_element = $("#map_canvas");
	var map_overlay_cont = $("<div>").attr("id", "map_loading_overlay").css({
		'display': 'none',
		'text-align': 'center',
		'background': '#FFFFFF',
		'position': 'absolute',
		'width': map_element.css("width"),
		'height': map_element.css("height"),
		'top': 0,
		'left': 0
	});
	var loading_img = $("<img>").attr("id", "maps_loading_image").attr("src", "/pws/images/ajax-loader-payment.gif");
	var loading_msg = $("<div>").attr("id", "maps_loading_text").html("Please wait while we find your nearest store...");
	
	loading_img.css({"margin-top": "120px"});
	loading_msg.css({"margin-top": "120px", "font-size": "2em"});
	
	var overlay_progress_box = $("<div>").attr("id", "overlay_progress").css({
		'border': '1px solid #0b67b2',
		'width': '200px',
		'margin': '36px auto 16px auto'
	});
	var overlay_progress_bar = $("<div>").attr("id", "overlay_progress_bar").css({
		'background': '#0b67b2',
		'width': '0px',
		'height': '15px'
	});
	
	var map_overlay = map_overlay_cont.append(loading_msg).append(overlay_progress_box.append(overlay_progress_bar));
	
	map_element.append(map_overlay);
	map_overlay.fadeTo(1, 0, function(){ $(this).css("display", "block").fadeTo(500, 0.8); });
}

function hideMapOverlay()
{
	$("#map_loading_overlay").fadeTo(500, 0, function(){
		$(this).css("display", "none");
	});
}

var userPoint;
var userMarker;
var pointsLoaded = 0;

function getDurationToPoint(fromLoc, store, attemptNumber, debug_ID)
{
	// get duration for each point
	var directions = new GDirections();
	
	var query = "from: " + fromLoc.getLatLng().lat() + "," + fromLoc.getLatLng().lng() + " to: " + store.lat() + "," + store.lng();
	directions.load(query);
	directions.loaderNum = debug_ID;
	directions.storeLoc = store;
	directions.storeID = store.storeID;
	
	var loader;
	var catcher = false;
	
	GEvent.addListener(directions, "load", function(){
		// if catcher is true then method has been cancelled due to process taking too long
		if(!catcher){
			// store success so clear timeout
			clearTimeout(loader);
			pointsLoaded++;
			addToList(null, linkedList, this.getDuration().seconds, this);
			updateProgressBar(pointsLoaded);
			
			if(pointsLoaded == maxStores){
				postcodeDisplay();
			}
		}
	});
	
	// set timeout incase store fails
	loader = setTimeout(function(){
		// 3 attempts before stores fail
		if(attemptNumber < 3){
			catcher = true;
			getDurationToPoint(fromLoc, store, attemptNumber+1, debug_ID);
		}
		else{
			if($("#map_loading_overlay").length){
				$("#maps_loading_text").html("Taking too long? Why not search by region instead or try refreshing the page");				
			}
		}
	}, 2000);
}

function getDuration(fromLoc)
{
	for(var count = 0 ; count < point.length ; count++)
	{
		// calculate the distance between postcode long/lat and store long/lat as the crow flies
		var storePoint = point[count];
		
		// distance = root(x^2 + y^2)
		var x = storePoint.lat() - fromLoc.getLatLng().lat();
		var y = storePoint.lng() - fromLoc.getLatLng().lng();
		var pointDistance = Math.sqrt(x*x + y*y);
		
		addToTempList(null, calculatedList, pointDistance, storePoint);
	}
	
	var store_count = 0;
	var tempStoresArray = calculatedList;
	// prevent code from searching over the amount of stores available
	if(pointCount < maxStores) maxStores = pointCount;
	if(pointCount <= maxStores) buffer = 0;
	
	while(store_count < maxStores + buffer && !(tempStoresArray == null))
	{
		getDurationToPoint(fromLoc, tempStoresArray.point, 0, store_count+1);
		tempStoresArray = tempStoresArray.next;
		store_count++;
	}
}


function displayDirections(fromLoc, toLong, toLat, storeID)
{
	var query = "from: " + fromLoc.getLatLng().lat() + "," + fromLoc.getLatLng().lng() + " to: " + toLong + "," + toLat;
	GEvent.addListener(directions2, "load", function(){
		$("#directions_loading").fadeTo(300, 0, function(){$(this).css("display", "none");});
		$("img.maps_loading_directions").remove();
	});
	directions2.load(query);
}

function addCustomMarker(userMarker, redrawMap)
{
	map.addOverlay(userMarker);
			
	GEvent.addListener(userMarker, "click", function(cMarker) {
		//console.log("user marker clicked");
	});
	if(redrawMap){
		centerPoint = bounds.getCenter();
		zoomLevel = map.getBoundsZoomLevel(bounds);
		map.setCenter(centerPoint, zoomLevel);
	}
}

function displayError(method, storeID)
{
	switch (method){
		case("directionsTo"):
			var element = $("div#popup_content_" + storeID + " div.directions_finder");
			element.find("img.maps_loading_directions").remove();
			$("div#directions_loading").fadeTo(800, 0, function(){
				$(this).append("Sorry, your postcode wasn't recognised! Please double check it and try again.").fadeTo(800, 1);
			});
			break;
		case("duration"):
			
			var overlay_progress_box = $("<div>").attr("id", "maps_postcode_error").css({
				'font-size': '1.6em'
			});
			overlay_progress_box.html("Sorry, your postcode wasn't recognised! Please double check it and try again.");
			$("div#maps_loading_text").fadeTo(300, 0);
			$("div#overlay_progress").fadeTo(300, 0);
			
			$("div#map_loading_overlay").append(overlay_progress_box);
			
			break;
		default:
			break;
	}
}

function createCustomMarker(method, postcode, fromLong, fromLat, storeID){
	postcode = postcode.replace(" ", "");
	
	switch (method){
		case("directionsTo"):
			$("#directions_loading").css("display", "block").fadeTo(300, 0.8);
			$("#map_canvas").animate({
				width: "650px"
			}, function(){
				$(directions_list).css("display", "block").css({
					"width": "263px",
					"margin-left": "7px",
					"position": "relative"
				});
			});
				
			break;
		case("duration"):
		
			break;
		default:
			break;
	}
	
	
						
	$.ajax({
		url: "/storedata/storeimport/fcp-content?postcode=" + postcode,
		success: function(data, textStatus) {
			var hasError = data.indexOf("IOException");
			if(hasError >= 0){
				if(method == "duration") displayMapOverlay();
				displayError(method, storeID);
			}
			else{
			
				// get the first lat and the first long
				var user_lat = data.substring(data.indexOf("<latitude>") + 10, data.indexOf("</latitude>"));
				var user_long = data.substring(data.indexOf("<longitude>") + 11, data.indexOf("</longitude>"));
				
				userPoint = new GLatLng( user_lat, user_long );
				userMarker = new GMarker(userPoint, markerOptions);
				
				switch (method){
					case("directionsTo"):
						if(!directions2) directions2 = new GDirections(map, directions_list);
						displayDirections(userMarker, fromLong, fromLat, storeID);
						break;
					case("duration"):
						displayMapOverlay();
						getDuration(userMarker);
						break;
					default:
						break;
				}
			}
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			if(method == "duration") displayMapOverlay();
			displayError(method, storeID);
		}
	});
}

function directionsToHere(storeLong, storeLat, storeID){
	var postcode = $("div#popup_content_" + storeID).find("input.directions_postcode").attr("value");
	if(postcode === "") postcode = "xxxxxxx";
	$("div#popup_content_" + storeID + " div.postcode_lookup_element").append("<img class='maps_loading_directions' src='/pws/images/ajax-loader-maps-small.gif' />");
	createCustomMarker("directionsTo", postcode, storeLong, storeLat, storeID);
}

function displayOnMap(postcode){
	createCustomMarker(postcode);
	addCustomMarker(userMarker, false);
}

function setupPopupFunctions(){
	$("button.directions_submit").unbind("click").click(function(){
		var container = $(this).parents("div.infowin_content");
		var store_id = container.attr("id").substring(container.attr("id").lastIndexOf("_") + 1, container.attr("id").length);
		var long = container.find("span.longitude:first").html();
		var lat = container.find("span.latitude:first").html();
		directionsToHere(lat, long, store_id);
		return false;
	});	
}

function setupPrinting(){
	$("a.print_stores").click(function(){
		window.print();
		return false;
	});
}

$(document).ready(function(){
	$("select#country, select#region").change(function(){
		if($(this).val()){
			if($(this).is("#country")){
				$("select#region").val("").attr("disabled",true);
			}
			$(this).parents("form:first").submit();
			$("#store_finder_select button.type_g").addClass("type_g_disabled").removeClass("type_g").click(function(){
				return false;
			});
		}
	});
	if(!$.browser.msie){
		$("#store_finder select#region").focus(function(){
			$("option[value='']").attr("disabled",true);
		});
	}
	setupPrinting();
});

