jQuery.fn.outerHTML = function(s) {
    return (s)
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
}




// WTB global vars
var __map = null;
var __storeData = null;
var __markers = [];
var __directionsMode = false;
var __baseUrl = null;
var __icon = "";
var __declutterIcon = "";
var __routeMarkers = null;
var __route = {};

var CodeDom = {
	property: function(obj, name) {
		var internalName = '_' + name;
		obj[internalName] = null;
		obj['get_' + name] = function() {
			return this[internalName];
		};
		obj['set_' + name] = function(value) {
			this[internalName] = value;
		};
	},
	properties: function(obj, names) {
		var length = names.length;
		for (var i = 0; i < length; i++)
			this.property(obj, names[i]);
	}
};


var __mapContext = {

	get_store: function(index) {
		var storeData = this.get_storeData();
		// check array bounds
		return storeData.records[index];
	}
};

CodeDom.properties(__mapContext, ['map', 'storeData', 'markers', 'directionsMode', 'baseUrl', 'icon', 'declutterIcon', 'routeMarkers', 'route' ]);


function _getMapContext() {
	return __mapContext;
}

function getDeclutterIcon() {
    return _getMapContext().get_declutterIcon();
}

function setBaseUrl(url) {
	_getMapContext().set_baseUrl(url);
}

function getAjaxUrl(url) {
    return _getMapContext().get_baseUrl() + url;
}

function populateNearestStockist(val) {
	var val = $("#ml_centre").val();
	if (val == "JE4 8NN") {
		val = "Jersey";
		updateLocationUI("#Channel_Islands", "Channel Islands");
	} else {
		updateLocationUI("#UK_Mainland", "UK Mainland");
	}

	$("#ml_refine").val(val);
}

function updateLocationUI(jqCheckId, locationName) {
	$(jqCheckId).attr("checked", "checked");
	$(".search-drop #location strong a").outerHTML(locationName);
}

function initMap(container) {
	var map = MMFactory.createViewer(container);
	//map.goToPosition(new MMLocation("UK", 15));
	//map.goToPosition(new MMLocation(new MMLatLon(54.57206, -3.55957), 6));
	map.drawAndPositionMap(new MMLocation(new MMLatLon(54.57206, -3.55957), 6));
	 
	//map.addWidget(new MMPanZoomWidget(new MMBox(70, null, null, 10)));
	//map.addWidget(new MMMapTypeWidget(null, new MMBox(10, null, null, 10)));
	map.addWidget(new MMPanZoomWidget(new MMBox(70, undefined, undefined, 10)));
	map.addWidget(new MMMapTypeWidget(undefined, new MMBox(10, undefined, undefined, 10)));
	map.addEventHandler("declutterCluster", function(eventType, mapViewer, declutterType, groupName, markerArray, markerOverlay) {
    	markerOverlay.reset(null, { label: "Several dealers close together" });
	});
	_getMapContext().set_map(map);
}


function getIcon() {
    return _getMapContext().get_icon();
}

function getMap() {
	return _getMapContext().get_map();
}

function _wtbGeocode(q, cc, callback) {
    $.ajax({
	   
		url: getAjaxUrl("geocode.ashx"),
		type: "GET",
		data: {
			q: q,
			cc: cc
		},
		dataType: "json",
		success: function(data, textStatus) {
			callback(data.d);
		}
	});
}

function _wtbSearch(lat, lon, freestanding, vacuum, builtin, wine, callback) {
	$.ajax({
		url: getAjaxUrl("query.ashx"),
		type: "GET",
		data: {
			lat: lat,
			lon: lon,
			freestanding: freestanding,
			vacuum: vacuum,
			builtin: builtin,
			wine: wine
		},
		dataType: "json",
		success: function(data, textStatus) {
			callback(data.d);
		}
	});
}

function doSearch() {

	window.setTimeout(function() {

		$("#mapContainer").show();

		var searchTerm = $("#ml_refine").val();
		//var countryCodes = ($("input[@name='ml_country']:checked").length > 0) ? $("input[@name='ml_country']:checked").val() : "GB";

		var countryCodes = $("input[@name='ml_country']:checked").val();
		if (countryCodes == "")
			countryCodes = "GB";

		//var countryCodes = countryCodesVal.split("|");
		var freestanding = $("#freestanding").is(":checked");
		var vacuum = $("#vacuum").is(":checked");
		var builtin = $("#builtin").is(":checked");
		var wine = $("#wine").is(":checked");
		
		_getMapContext().get_map().removeAllOverlays();
		_getMapContext().set_markers([]);
		loadingStatus(true);


		_wtbGeocode(searchTerm, countryCodes, function(data) {
			if (data.locations.length < 0) {
				// TODO
				// Display template to indicate no search results returned.
				alert('Sorry your search returned no results, please try again.');
			}
			else {
				var loc = data.locations[0];
				var lat = loc.point.lat;
				var lon = loc.point.lon;


				window.setTimeout(function() {

					_wtbSearch(lat, lon, freestanding, vacuum, builtin, wine, function(data) {

						var defaultLoc = new MMLocation(new MMLatLon(lat, lon));

						var context = _getMapContext();
						context.set_storeData(data);
						setupMarkers(context.get_storeData().records);
						try { context.get_map().declutterGroup(context.get_icon().groupName, { 'cluster_icon': context.get_declutterIcon() }); } catch (ex) { }
						displayStoreSearchResult(5);
						locateOnMap(undefined, defaultLoc);
						loadingStatus(false);
					});

				}, 100);

			}
		});

	}, 100);

	return false;
}


function gotoRouteMarker(step) {
    _getMapContext().get_routeMarkers()[step].openInfoBox()
}


function getDirections(callingButton) {
    var directionsFrom = $(callingButton).parent().parent().find("#mi_directions").val();
    var numberRegex = /\d/g;
    var letterRegex = /[a-z]+/g;

    var containsNumbers = numberRegex.test(directionsFrom);
    var containsLetters = letterRegex.test(directionsFrom);
    
    if ((containsLetters && !containsNumbers) || (containsLetters && containsNumbers && postCodeValid(directionsFrom))) {
        var num = $(callingButton).parent().parent().find("#mi_sequence").val();
        getRoute(num, directionsFrom, _getMapContext().get_store(num - 1));
    } else {
        alert('Please enter a valid postcode or town name.');
    }
}

function clearPreviousSearch() {
    $("#spotlightContainer").html("");
    $("#searchResultsContainer").html("");
    $("#moreResultsContainer").html("");
}


function displayStoreSearchResult(maxResultsInMainPane) {
    clearPreviousSearch();
    var recordsToDisplay = _getMapContext().get_storeData().records;
    $("#spotlightContainer").append("#nearestSearchResultTemplate", recordsToDisplay.slice(0, 1));
    $("#searchResultsContainer").append("#listedSearchResultTemplate", recordsToDisplay.slice(1, maxResultsInMainPane));
    $("#moreResultsContainer").append("#listedSearchResultTemplate", recordsToDisplay.slice(maxResultsInMainPane));
}


function setupMarkers(records) {
	var markers = [];
	var length = records.length;
    for (var i = 0; i < length; i++) {
        var marker = createMarker(records[i],i+1);
        markers.push(marker);
    }
    _getMapContext().set_markers(markers);
}


function addRouteOverlay() {
    var poly;
    var map = _getMapContext().get_map()
    var route = _getMapContext().get_route();
	for (var i = 0, j = route.polyLine.length; i < j; i++) {
	    route.polyLine[i].reset(route.polyLine[i].points, { 'opacity': 0.6, 'color': undefined, 'thickness': 1.0 });
	    map.addOverlay(route.polyLine[i])
	}
}

function showRoute(num, from, to) {
    var map = _getMapContext().get_map();
    var route = _getMapContext().get_route();
    if (route.geocoding_errors) {
		alert("No location found.");
	} else {
		map.removeAllOverlays();
		addRouteOverlay();
		displaySteps();
		map.goToPosition(map.getAutoScaleLocation(route.bounds));
		// Display store.
		map.addOverlay(_getMapContext().get_markers()[num - 1]);
    }
}


function displaySteps() {
	var step, html;
	html = [];
	var routeMarkers = [];
	var route = _getMapContext().get_route();
	var num = 0;
	for(var i = 0, j = route.stages.length; i < j; i++) {
		for(var k = 0, l = route.stages[i].steps.length; k < l; k++) {
		    step = route.stages[i].steps[k];
		    num++;
		    var routeMarker = createRouteMarker(step,num);
		    routeMarkers.push(routeMarker);
		}
    }
    _getMapContext().set_routeMarkers(routeMarkers);
	this.getHtmlRoute();
}


function createRouteMarker(step,num) {
    var icon = createIcon();
    icon.groupName = 'o2';
    var declutterIcon = createIcon(true);
    var location = new MMLocation(new MMLatLon(step.start_point.lat, step.start_point.lon));
    location.zoom_factor = 31700;
    var marker = _getMapContext().get_map().createMarker(location);
    marker.setInfoBoxContent("<p>" + num + ".</p>");
    return marker;
}


function roundMiles(value) {
    if (value < 1) {
        return value;
    } else {
        return Math.round(value);
    }
}

function getHtmlRoute() {
    
    var route = _getMapContext().get_route();
    var routeMarkers = _getMapContext().get_routeMarkers();
    var me = this;
    var curr_step = 1;
    var stages = route.stages;
    var headerModel = new Object();

    var summary = ""; 
    if(route.duration.days > 0) { summary += route.duration.days + ' day(s) '; }
	if(route.duration.hours > 0) { summary += route.duration.hours + ' hour(s) '; }
	if(route.duration.minutes > 0) { summary += route.duration.minutes + ' minute(s) '; }

	headerModel["total_distance"] = route.distance.miles;
    
    headerModel["summary"] = summary;
    var directionsOuterTemplateHTML = $("#directionsOuterTemplate").render(headerModel).outerHTML();
    var directionsStageTemplateHTML = "";
        
    for (var count = 0; count < stages.length; count++) {

        var steps = stages[count].steps;
        var stageModel = stages[count];

        stageModel["ol_id"] = 'stage_' + count;
        stageModel["start"] = curr_step
        stageModel["stage_number"] = count;
        
        directionsStageTemplateHTML += $("#directionsStageTemplate").render(stageModel).outerHTML();
        // ---------------------------------------------------------------
        var stepsHTML = "";
        
        for (var stepCount = 0; stepCount < steps.length; stepCount++) {
            
            var stepObject = new Object();
            // Label the current marker with the step number:
            var text = curr_step;
            // Make the higher numbered step markers appear 'on top of' lower ones:
            var zindex = 1000 - curr_step + 1;

            // Use 'S' as marker text if this is the first step of the entire route:
            if (count == 0 && stepCount == 0) {
                text = 'S';
            }
            // Use 'F' as marker text if this is the last step of the entire route:      
            if (count == stages.length - 1 && stepCount == steps.length - 1) {
                text = 'F';
                zindex = 1000;
            }
            
            // Create a written 'instruction' using the roadname and/ or roadnumber:
            var instruction = steps[stepCount].instruction;
            var roadname = steps[stepCount].road_name;
            var roadnumber = steps[stepCount].road_number;
            if (roadname && roadnumber) {
                instruction += ' ' + roadname + ' (' + roadnumber + ') ';
            } else if (roadname) {
                instruction += ' ' + roadname + ' ';
            } else if (roadnumber) {
                instruction += ' ' + roadnumber + ' ';
            }

            // Show the distance of this particular step:
            var distance = '';
            if (steps[stepCount].distance.miles > 0) { distance += steps[stepCount].distance.miles + ' mile(s) '; }
            if (distance != '') { distance = ' - ' + distance };
            stepObject["link_step_number"] = stepCount;
            stepObject["link_text"] = instruction + distance;
            ++curr_step;

            stepsHTML += $("#directionsStageStepsTemplate").render(stepObject).outerHTML();
        }
        directionsStageTemplateHTML = directionsStageTemplateHTML.replace("STEPS", stepsHTML);
        // -----------------------------------------------------------------
    }
    
    directionsOuterTemplateHTML = directionsOuterTemplateHTML.replace("STAGES",directionsStageTemplateHTML);
    $("#directions").html(directionsOuterTemplateHTML);
        
}




function getRoute(num, from, to) {
    if (from.length > 4 && from != "From") {
        _getMapContext().set_directionsMode(true);
        _getMapContext().set_routeMarkers([]);
        var me = this;
        var searcher = MMFactory.createRouteRequester(function() {
            me.showRoute(num, from, to, this);
        }, _getMapContext().get_map());
        var locations = [];
        locations.push(new MMAddress({ 'qs': from, 'country_code': 'GB' }));
        locations.push(new MMLocation(new MMLatLon(to.point.lat,to.point.lon)));
        var route = new MMRoute(locations);
        _getMapContext().set_route(route);
        searcher.request(route);
    }
}
    		

function clearDirectionSteps() {
	_getMapContext().set_directionsMode(false);
    $("#directions").html("");
}

function redisplayMarkers() {
    if (_getMapContext().get_directionsMode()) {
    	clearDirectionSteps();
    	var map = _getMapContext().get_map();
    	var markers = _getMapContext().get_markers();
    	map.removeAllOverlays();
    	var length = markers.length;
        for (var i = 0; i < length; i++) {
            map.addOverlay(markers[i]);
        }
        locateOnMap();
    }
}

function createIcon(declutter) {
	var icon = "";
	if(!declutter) {
		icon = new MMIcon("images/red_circle.png");
		icon.iconSize = new MMDimensions(20, 20);
		icon.iconAnchor = new MMPoint(16, 16);
		_getMapContext().set_icon(icon);
	}
	else {
		icon = new MMIcon("../products/images/icons/map_close.gif");
		icon.iconSize = new MMDimensions(20, 20);
		icon.iconAnchor = new MMPoint(16, 16);
		_getMapContext().set_declutterIcon(icon);
	}
	return icon;
}


function createMarker(record,num) {
    var icon = createIcon();
    icon.groupName = 'o2';
    var declutterIcon = createIcon(true);
    var location = new MMLocation(new MMLatLon(record.point.lat, record.point.lon));
    location.zoom_factor = 31700;
    var marker = _getMapContext().get_map().createMarker(location, { "text": num, "icon": icon, "label": num + ". " + record.fields.name });
    marker.setInfoBoxContent(createInfoBox(record, num));
    return marker;
}


function createInfoBox(record,num) {
    var tabs = [];
    tabs.push(new MMInfoBoxTab("Info", this.createTab1(record, num)));
    if (record.fields.monday.length>0) tabs.push(new MMInfoBoxTab("Opening", this.createTab2(record)));
    if (record.fields.about.length > 0) tabs.push(new MMInfoBoxTab("About", this.createTab3(record)));
    if(record.fields.photos)
    	if (record.fields.photos.length > 0)
			tabs.push(new MMInfoBoxTab("Gallery", this.createTab4(record)));
    return tabs;
}


function createTab1(record, num) {
    var doc = document;
    var div = $("#infoBoxTab1").render(record).get(0);
    return div;
}

function createTab2(record, num) {
    var doc = document;
    var div = $("#infoBoxTab2").render(record).get(0);
    return div;
}

function createTab3(record, num) {
    var doc = document;
    var div = $("#infoBoxTab3").render(record).get(0);
    return div;
}


function createTab4(record, num) {
    var doc = document;
    var div = doc.createElement("div");
    div.innerHTML = "TAB 4";
    return div;
}


function showFirstLocation() {
	_getMapContext().get_map().goToPosition(_getMapContext().get_store(0));
}


function locateOnMap(index, defaultLoc) {
    // arguments[0] will be the index position in the marker array/store data plus 1. So we take 1 from it to get the array index pos.
    var markers = _getMapContext().get_markers();
	if(index) {
	    //this.map.goToPosition(new MMLatLon(arguments[0].lat, arguments[0].lon), 15);
		markers[index - 1].openInfoBox();
		galleryCheck();
	} else {
		var map = _getMapContext().get_map();
		//map.resetPosition();
		if (markers.length == 0 && defaultLoc) {
			map.goToPosition(defaultLoc);
		} else {
			map.goToPosition(map.getAutoScaleLocation(markers));
		}
	}
}




function loadingStatus(loading) {

    var doc = document;
    //var f = doc.getElementById("stockist-search-1");
    var l = doc.getElementById("loader");
    var r = doc.getElementById("resetButton");

    l.style.display = loading ? 'block' : 'none';
    //f.style.visibility = loading ? 'hidden' : 'visible';
    r.style.visibility = loading ? 'hidden' : 'visible';
   }


function galleryCheck() {
   vsWidth = 192;
   vsTotal = $(".photo-scroller .mask ul li").length;
   vsShowing = 1;
   vsVisible = 1;
   img_labels = new Array();
   array_i = 0;
   $(".mask ul li img").each(
	function() {
	    img_labels[array_i] = $(this).attr("alt");
	    array_i++;
	    }
    );
   $(".photo-scroller .mask ul").css("left", "0px");
   if (vsTotal > 1) {

       //Set width of image container
       $(".photo-scroller .mask ul").css({ "width": vsWidth * vsTotal + "px" });
   }
   $(".photo-indicator ol li").remove();
   for (i = 1; i <= vsTotal; i++) {
       //photo indicator dots
       if (i <= vsVisible) {
           $(" .photo-indicator ol").append("<li class=\"showing\">" + i + "</li>");
       } else {
           $(" .photo-indicator ol").append("<li>" + i + "</li>");
       }
   }
   $(" .photo-indicator p").text(vsTotal + " ");
   if (vsTotal > vsVisible) {
       $(".photo-scroller .next a").removeClass("inactive");
   }
   $(".photo-scroller .previous a").click(
	    function() {
	        // NOT IMPLEMENTED..
	    }
    );
}





$(document).ready(function() {

	if ($("div.MMMarker")) {
		$("p#stockist-key").show();
	}
	//$("#mapContainer").hide();

	var regionShowing = 0;

	$("#region a").click(
		function() {


			if (regionShowing == 0) {

				$("#region-opts").show();
				regionShowing = 1;

			} else if (regionShowing == 1) {

				$("#region-opts").hide();
				regionShowing = 0;

			}

		}
	);

	$("#region-opts label").click(
		function() {

			$("#region-opts label").removeClass("selected");
			$(this).addClass("selected");
			$("#region-opts").hide();
			regionShowing = 0;
			$("#region a").html($(this).html());

		}
	);

	$("#stockist-search-1 .button a").click(
		function() {

			if (wtbValidateLocation())
				$("#stockist-search-2").slideDown();

			return false;

		}
	);

	$(".input-field").focus(
		function() {

			$(this).val("");

		}
	);

	$(".input-field").blur(
		function() {

			if ($(this).val() == "") {
				$(this).val($(this)[0].defaultValue);
			}

		}
	);

	function wtbValidateLocation() {
		var refineText = jQuery.trim($("#ml_refine").val());
		if (refineText.length < 1 || refineText == "Enter town or postcode" || refineText == "Type in town or postcode") {
			if ($("#refine-warning").length < 1)
				$("#stockist-search-1").before("<p id=\"refine-warning\">Please enter a postcode or location</p>");
			return false;
		}
		else {
			$("#refine-warning").remove();
			return true;
		}
	}

	function wtbValidateOptions() {

		if ($("ul.cat input:checked").length < 1) {

			if ($("#search-warning").length < 1) {
				$("#stockist-search-2").slideDown();
				$("#stockist-search-2").before("<p id=\"search-warning\">Please select at least one category: Freestanding Appliances, Built-in Appliances, Vacuum Cleaners or Wine Appliances</p>");
			}
			return false;

		}
		else {
			$("#search-warning").remove();
			return true;
		}
	}

	function wtbValidateForm(ev) {
		if (!wtbValidateLocation()) {
			ev.preventDefault();
			ev.stopPropagation();
			return false;
		}
		else if (!wtbValidateOptions()) {
			ev.preventDefault();
			ev.stopPropagation();
			return false;
		}
		else {
			return true;
		}
	}

	$("#wtbsearch").click(function(ev) {
		$("form:first").submit();
		ev.preventDefault();
		ev.stopPropagation();
		return false;
	});

	$("form.wtbform1").submit(function(ev) {

		return wtbValidateForm(ev);
	});
	$("form.wtbform2").submit(function(ev) {

		if (!wtbValidateForm(ev)) {
			return false;
		} else {
			doSearch();
			return false;
		}
	});

	//
	// version 2
	//


	$("#ml_centre").change(function() {
		populateNearestStockist();
	});


	//$("#mapContainer").hide();
	initMap($("#mapContainer").get(0));

	//_getMapContext().get_map().goToPosition(new MMLocation(new MMLatLon(54.57206, -3.55957), 6));
	//_getMapContext().get_map().goToPosition(new MMLocation("UK", 15));
	//$("#mapContainer").fadeIn();

});





function postCodeValid(postCode) {
    var __rxPostCode = /(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) ?[0-9][ABD-HJLNP-UW-Z]{2})/i;
    return (__rxPostCode.test(postCode));
}

