// Component javascript 
// 
// Reads data and creates a simple tag representation of it, which is (mostly!) styled with CSS. 
//

var w, h;
var requiredLanguage;
var moListStyle;
var moDays;
var moFSSI;
var moLocation = null;
var moColourScheme;
var moMapDisplay;
var moMapsRequired;
var moTemperatureUnits;
var moSpeedUnits = "M";
var moShowWind;
var moShowUV;
var moShowFeelsLike;
var moAllowUserLocation;
var textWindUnits = "mph";
var labels = {};
var moSpecificWidth = 0;
var moSpecificHeight = 0;

var weathermapURL = "http://www.metoffice.gov.uk/weather/uk/uk_forecast_weather.html";
var maxFontSize = 18; // max font-size in px
var desiredWidth = 160; // i.e. width - padding

var mapArea;
var displayPeriod;
var transparentFileSuffix = ($.browser.msie ? "gif" : "png");
var uvSymbol =     ["", "green", "green", "yellow", "yellow", "yellow", "orange", "orange", "red", "red", "red", "purple"]; // 0 left blank as UV values range from 1 to 11;
var uvTextColour = ["", "white", "white", "#555555", "#555555", "#555555", "black", "black", "white", "white", "white", "white"]; // 0 left blank as UV values range from 1 to 11;

$(document).ready(function () {
	var userLanguage = $.cookie("moLanguage");
	if (userLanguage == null) {
		requiredLanguage = component.getQueryString("moStartupLanguage");
	} else {
		requiredLanguage = userLanguage;
	}
    setupLanguage(requiredLanguage);
	initialize();
});

function initialize() {
	// get parameters
	moMapDisplay = component.getQueryString("moMapDisplay");
	moMapsRequired = component.getQueryString("moMapsRequired");
	moListStyle = component.getQueryString("moListStyle");
	moListStyle = "vertical";
	moDays = component.getQueryString("moDays");
	moFSSI = component.getQueryString("moFSSI");
	
/*----- FIX: CR 17,655 ---------to hopefully be removed in the future--------------------------------------------------------------------------------------------
The following siteMap array is linked to a post release fix to handle missing sites. 
When 5000 sites was implemented the following sites were removed as they were deemed unneeded due to better alternatives.
The problem lies because some people with the old release of the widget may have created it for a site with one of the IDs that have now been removed. 
Therefore we have to add in logic to map those widgets to a new ID (one that has data available) in order to avoid breaking the customers widgets.
-------Josh Wreford-------------------------------------------------------------------------------------------------------------------------------*/
	var siteMap = [];
		siteMap["3501"] = "350021"; siteMap["3927"] = "350232"; siteMap["4"] = "350426"; siteMap["3717"] = "350758"; siteMap["3154"] = "351271"; siteMap["3160"] = "351351"; 
		siteMap["3527"] = "351670"; siteMap["99040"] = "351968"; siteMap["3347"] = "352241"; siteMap["3779"] = "352409"; siteMap["3246"] = "352793"; siteMap["3114"] = "352889";
		siteMap["3791"] = "353466"; siteMap["99044"] = "353467"; siteMap["3683"] = "353656"; siteMap["99053"] = "354005"; siteMap["3776"] = "353185"; 
	if (siteMap[moFSSI]) {moFSSI = siteMap[moFSSI];}
/*-----end array for fix------------------------------------------------------------------------------------------------------------------------------*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	moColourScheme = component.getQueryString("moColourScheme");
	moTemperatureUnits = component.getQueryString("moTemperatureUnits");
	moSpeedUnits = component.getQueryString("moSpeedUnits");
	moShowWind = component.getQueryString("moShowWind");
	moShowUV = component.getQueryString("moShowUV");
    moShowFeelsLike = component.getQueryString("moShowFeelsLike");
    moAllowUserLocation = component.getQueryString("moAllowUserLocation");
    
    if (moAllowUserLocation == "true") {
        $("#optionsLocationContainer").show();
    }
    
	h = component.getQueryString("h");
	w = component.getQueryString("w");

	setNecessaryStyling();	 // this is exceptional styling that has to be set dynamically rather than in CSS.

	// apply the colour scheme
	$("#mainContainer").addClass(moColourScheme);
	$("#mainWrapper").addClass(moColourScheme);
	
	// IE version of above!
	switch(moColourScheme) {
		case "default": $("#mainWrapper").css("border-color", "Gray"); break;
		case "green": $("#mainWrapper").css("border-color", "#ccff33"); break;
		case "blue": $("#mainWrapper").css("border-color", "#031f73"); break;
		case "yellow": $("#mainWrapper").css("border-color", "#ffff66"); break;
	};
	
	// set the map position
	$("#maps").addClass(moMapDisplay);
	$("#nonmap").addClass(moMapDisplay);
	
	loadComponent();
}
	
function loadComponent() {	
	// set up loading images & note
	$("#location span").html(labels.general.loading);
    resizeText();
	$('#icon').html("<img src=\"../images/ajax-loader" + moColourScheme + ".gif\" />");

    $("#optionslink").unbind("click").click(showOptions);
    
	// Show day or night time?
	displayPeriod = getDisplayPeriod();
	
	if (moSpeedUnits){
        textWindUnits = labels.weather.wind[moSpeedUnits];
	}

	// get the advert.
	// if not found, we hide the advert URL.Still enable widget loading if an adblocker employed
	try {
        $.ajax({url: "data/adverts.xml", 
            method: "GET",
            success: processAdvert,
            error: adError, 
            timeout: 15000,
            cache: true
        });
    } 
    catch(err) {}

	// get the location name.
	// if not found, we show an error message.
	MetOffice.locations.getById(moFSSI, processLocationData, showError);

	component.displayHeaderWarning(requiredLanguage, labels.weather.warnings);

}

function setupLanguage(language) {
    var result = {};
	$.ajax({url: "/public/pws/components/lib/data/language/" + language + ".txt", 
		method: "GET",
		dataType: "json",
		async: false,
		success: function(data) {
            result = data;
		},
        failure: function() {
            result = {};
        },
		timeout: 15000, 
        cache: true
	});

    labels = result;
    setLabelText();
    $("body *").attr("dir", labels.language.direction).attr("lang", labels.language.code);
    $("#componentCSS").remove();
    
    var headID = document.getElementsByTagName("head")[0];         
    var cssNode = document.createElement('link');
    cssNode.type = 'text/css';
    cssNode.rel = 'stylesheet';
    cssNode.href = 'component' + labels.language.direction + '.css';
    cssNode.media = 'screen';
	cssNode.id = "componentCSS";
    headID.appendChild(cssNode);			
}

function setLabelText() {
    // options panel
    $("#optionsHeader").html(labels.options.header);
    $("#optionslink").attr("title", labels.link.alt.options);
    $("#optionslink").html(labels.link.text.options);
    $("#optionsSaveContents").html(labels.options.save);
    $("#optionsCancelContents").html(labels.options.cancel);
    $("#optionsForecastSelectionCancelContents").html(labels.options.cancel);
    $("#optionsLocationSearchContents").html(labels.options.search);
	$("#optionsLocationMessage").html(labels.options.location);
	$("#optionsForecastSelectionPanelMessage").html(labels.options.locationselect);
    $("#optionsLanguageMessage").html(labels.options.language);

    // help link
    $("#helplink").attr("href", labels.link.url.help);
    $("#helplink").attr("title", labels.link.alt.help);
    $("#helplink").html(labels.link.text.help);

    // more details link
    $("#moredetaillink").attr("title", labels.link.alt.moredetails);
    $("#moredetaillink").html(labels.link.text.moredetails);

    // Copyright link
    $("#copyright a").attr("title", labels.link.alt.copyright);
    $("#copyright a").html(labels.link.text.copyright);
    $("#copyrightsymbol").html("&copy;");

    $("#logo a").attr("title", labels.link.alt.metoffice);
    $("#logo img").attr("alt", labels.link.alt.logo);
}

function getDisplayPeriod() {
	$.ajax({url: "/public/data/WCCache/Item/DisplayPeriod", 
		method: "GET",
		async: false,
		success: function(data) {
			try {
				data = data.toLowerCase().substr(0,3);
				if (data == "day") {
					displayPeriod = "day";
				} else {
					displayPeriod = "night";
				}
			}
			catch(err) {
				displayPeriod = "day";
			}
		},
		error: function() {
			displayPeriod = "day";
		}, 
		timeout: 15000,
		cache: true
	});
	return displayPeriod;
}

function setNecessaryStyling() {

		// Only apply msie class if browser < 9
	if ($.browser.msie && $.browser.version <9) {
		$("#mainWrapper").addClass("msie");
		} else {
		// border inside / outside issues!
		h-=6;
		w-=10;
	}
			
	// setting the height helps styling layout in FF and Chrome on corners.  
	$("#mainWrapper").css("height", parseInt(h) + "px").css("width", parseInt(w) + "px");
   	$("#optionsLocationSearch").button();
   	$("#optionsSave").button();
   	$("#optionsCancel").button();
   	$("#optionsForecastSelectionCancel").button();
	$("#optionsForecastSelectionPanel").width(w - 30);
	$("#optionsLocation").width(w - 30);
}

function processAdvert(xml) {
	var adverts = $(xml).find("advert");
	var adCount = adverts.length;
	if (adCount === 0) {
		$("#advert").hide();
		return;
	};
	var chosenOne = Math.floor(Math.random() * adCount);
	var advert = $(adverts[chosenOne]);

	if (advert.attr("format") == "swf") {
		swfobject.embedSWF(advert.attr("image"), "advert", "180", "32", "9.0.0", "expressInstall.swf");
		$("#advert").wrapInner("<a href=\"" + advert.attr("href") + "\" title=\"" + advert.attr("title") + "\" target=\"_blank\"></a>")
	} else {
		$("#advert").html("<a href=\"" + advert.attr("href") + "\" title=\"" + advert.attr("title") + "\" target=\"_blank\"><img src=\"" + advert.attr("image") + "\"></a>")
	}

	$("#advert").addClass("active"); 
}

function adError() {
	$("#advert").removeClass("active");
}

function processMaps(xml) {
	var mapsArray = moMapsRequired.split(",");
	var multipleMaps = mapsArray.length > 1;
	var images = $(xml);
	var isImageOutput = false;
    
	$("#maps").html("").prepend("<div id=\"mapContainerGroup\">");
	for (var i in mapsArray) {
		var mapContainer = $("<div class=\"mapContainer\">");
		var layer = images.find("layer[type='" + mapsArray[i] + "']");
		var currentArea = ( layer.attr("type") == ("Pressure MSL") ? "wuk" : mapArea);
		var image = $(layer).find("image:first");
        var layerTitle = labels.layer[layer.attr("title")];
		if (image.length) {
			isImageOutput = true;
			var timestamp = new Date();
			timestamp.setISO8601(image.attr("timestamp"));
			var outputDate = timestamp.componentDateFormat(labels.calendar.month);
			mapContainer.append("<h2>" + layerTitle + "</h2>");
			mapContainer.append("<h3>" + outputDate + "</h3>");
			mapContainer.append("<div class=\"imageholder\">" + 
				"<img class=\"background\" src=\"../images/maps/" + currentArea + ".png\">" + 
				"<img class=\"middle\" width=\"150\" height=\"150\" alt=\"" + layer.attr("title") + "\" src=\"" + component.formatImageSource(image.attr("src"), currentArea, transparentFileSuffix) + "\" />" + 
				(layer.attr("type") == ("Pressure MSL") ? "" : "<img class=\"foreground\" src=\"../images/maps/" + currentArea + "Transparent." + transparentFileSuffix + "\">") + 
				"</div>" );
			mapContainer.appendTo("#mapContainerGroup");
		} else {
			mapContainer.append("<h2>" + layerTitle + "</h2>");
			mapContainer.append("<div class=\"imageholder\" style=\"background-color:#333333\">" + layer.attr("title") + labels.error.layernotretrievablepostamble + "</div>");
			mapContainer.appendTo("#mapContainerGroup");
		}
	}
	if (isImageOutput) {
		// wrap required instead of an inline href, because IE making overlays opaque with latter. 
		$(".imageholder img").attr("title", labels.link.alt.maps).wrap("<a target=\"_blank\" href=\"" + weathermapURL + "\" title=\"" + labels.link.alt.maps + "\"></a>");
		
		if (multipleMaps ) {
			$("#maps").prepend("<div class=\"previous nav\"><span><img src=\"../images/left.jpg\"></span></div>");
			$("#maps").append("<div class=\"next nav\"><span><img src=\"../images/right.jpg\"></span></div>");
			$(".next").click(nextMap);
			$(".previous").click(previousMap);
		} else {
			$(".nav").addClass("inactiveNav");
		}
		$(".mapContainer:first").addClass("current");
	}
}

function nextMap() {
	if (! $(".mapContainer.current").removeClass("current").next(".mapContainer").addClass("current").length) {
		$(".mapContainer:first").addClass("current");
	};
}

function previousMap() {
	if (! $(".mapContainer.current").removeClass("current").prev(".mapContainer").addClass("current").length) {
		$(".mapContainer:last").addClass("current");
	};
}


function processLocationData(location) {
	$("#location").css("zoom", 1);	// IE hasLayout fix
	var region = location.getRegion();
    
	// get the location name from the data.xml xml.  
	moLocation = location.getName();
    if(typeof(labels.places) != "undefined" && typeof(labels.places[moLocation]) != "undefined") {
        moLocation = labels.places[moLocation];
    }
    
	$("#location span").html(moLocation);
	resizeText();
	mapArea = component.getAreaCode(location.getLat(), location.getLon(), region);
	
	$("#moredetaillink").attr("href", "//www.metoffice.gov.uk/weather/uk/" + region + "/" + region + "_forecast_weather.html");  	// set up more details link


	// now get the forecast data.
	// if not found, we show an error message.
	MetOffice.forecast.getById(moFSSI, processWxData, showError);
}

function processWxData(data) {
	//add the maps
	if (moMapsRequired !== "") {
		$.ajax({url: "/public/data/WCCache/ItemList/Images/All", 
			method: "GET",
			success: processMaps,
			timeout: 15000,
			cache: false
		});
	}

	// get the weather data out of the forecast xml
	var counter = 0 ;
	var displayDate = internationalDate(data.days[0].date);
	
	$("#moredetail").show();	// show the more detail link.
	$("#date").html(displayDate + ((moShowWind == "true") ? " &bull; " + textWindUnits : "")).css("zoom", 1);	// show the date & wind units

	$("#content").html("<div class=\"days\"></div>");		// clear the panel ready for use
	$("#content").addClass(moListStyle);	// the moListStyle class is added, 
											// as this dictates the formatting of the days, which we add next. 

	for (var i = 0; i < data.days.length; i++) {
		counter++;
		appendDay(data.days[i], counter);	// adds to the document another div with the day's data in
		if (counter == moDays) break;		// stop adding days when got enough.
	}
											
	// set content to be in the middle (proving difficult in IE6 CSS)
	$("#content").css("margin-left", ( $("#content").width() - $(".days").width() ) / 2 + "px");
	//below: work around to fix positioning of "more details" when there are less than 5 days available in side map view.
	if (moMapDisplay == "side" && counter < moDays) {
		for (var c = counter;c<moDays;c++){
			var spaceFill = $("<div class=\"day\"><dl><dd></dd></dl></div>");
			spaceFill.appendTo("#content .days");
		}
	}
}

function appendDay(day, counter) {
	// creates a div for this day and adds a dl to it.  The dl contains dl and dt for each type of reading (temp, wind, etc).  
	var dayElement = $("<div class=\"day\">");
	var dl = $("<dl>");
	var thisDisplayPeriod = ((counter == 1) ? displayPeriod : "day");	// for the first day, we show day or night 
																		// appropriately, but for the remainder we show day only. 
	var wxData = day[thisDisplayPeriod];
	
	var thisDay = labels.calendar.day[day.date.split(" ")[0]];
	var thisFullDay = internationalDate(day.date);
	
	var thisTemperature = parseInt(parseFloat(wxData.temperature) + 0.5);
	var thisTemperatureUnits = labels.weather.temperature[moTemperatureUnits];
	if (moTemperatureUnits == "F") {
		thisTemperature = Math.round(((thisTemperature * 9) / 5) + 32);
	}

    // TODO: Mod to put correct value in.
	var thisFeelsLike = parseInt(parseFloat(wxData.feelsLike) + 0.5);
    
	if (moTemperatureUnits == "F") {
		thisFeelsLike = Math.round(((thisFeelsLike * 9) / 5) + 32);
	}
	
	var thisWindDirection = wxData.windDirection;
	var thisWindSpeed = parseInt(parseFloat(wxData.windSpeed) + 0.5);
	if (moSpeedUnits){
		if (moSpeedUnits == "K") {
			thisWindSpeed = Math.round(thisWindSpeed * 1.601);
		} else if (moSpeedUnits == "N") {
			thisWindSpeed = Math.round(thisWindSpeed * 0.868976242);
		}
	}
	if (counter === 1) {
		dl.append("<dt>Date</dt><dd class=\"date displayPeriod" + displayPeriod + "\" title=\"" + thisFullDay + "\">" + (displayPeriod == "day" ? labels.calendar.today: labels.calendar.tonight) + "</dd>");
	} else {
		dl.append("<dt>Date</dt><dd class=\"date\" title=\"" + thisFullDay + "\">" + thisDay + "</dd>");
	}
	dl.append("<dt>Weather</dt><dd class=\"weather\" title=\"" + (wxData.weather == null ? labels.weather.unknown : labels.weather.description[wxData.weather]) + "\">" + (wxData.weather === null ? "" : ("<img src=\"../images/wxsymbols/w" + wxData.weather + "." + transparentFileSuffix + "\">")) + "</dd>");
	dl.append("<dt>Temperature</dt><dd class=\"temperature\" title=\"" + labels.weather.temperatureType.temperature + " " + thisTemperature + "&deg;" + thisTemperatureUnits + "\">" + thisTemperature + "<span class=\"units\">&deg;" + thisTemperatureUnits + "</span>" + "</dd>");
	if (moShowWind == "true") {
		dl.append("<dt>Wind</dt><dd class=\"wind\" title=\"" + internationalDirection(thisWindDirection) + " " + thisWindSpeed + " " + textWindUnits + "\"><img src=\"../images/windSymbols/" + thisWindDirection + "." + transparentFileSuffix + "\"><label class=\"qty\">" + thisWindSpeed + "</label></dd>");
	}
	if (moShowFeelsLike == "true") {
        dl.append("<dt>Feels like</dt><dd class=\"feelsLike\" title=\"" + labels.weather.temperatureType.feelsLike + " " + thisFeelsLike + "&deg;" + thisTemperatureUnits + "\">" + thisFeelsLike + "<span class=\"units\">&deg;" + thisTemperatureUnits + "</span>" + "</dd>");
	}
	
	if (moShowUV == "true") {
		var tempUVValue = parseInt(wxData.UV);
		dl.append("<dt>UV</dt><dd class=\"uv\" title=\"" + (wxData.UV == null ? labels.weather.unknown : "UV: "+wxData.UV) + "\">" + (wxData.UV === null ? "" : ("<img src=\"../images/uvSymbols/" + uvSymbol[tempUVValue] + ".gif\"><label style=\"color:" + uvTextColour[tempUVValue] + "\" class=\"\">" + tempUVValue + "</label>")) + "</dd>");
	} 
	
	dl.appendTo(dayElement);
	dayElement.appendTo("#content .days");
}

function showError() {
	// sets up the panel with an appropriate error mesage
	
	$("#moredetail").show();
	$("#location span").html(labels.error.wxnotfound);
	resizeText();
    var textLocation = (moLocation === null || (typeof(moLocation) == "undefined") ? labels.general.location : moLocation)

	$("#content").html("<div class=\"wxnotfound\">" + labels.error.wxnotfoundpreamble + " " + textLocation + " " + labels.error.wxnotfoundpostamble + "</div>")
}

function showOptions() {
    $("#mainContainer").hide();
    $("#warning").hide();
    $("#optionsContainer").show();
    
    setupOptions();
}

function showMain() {
    $("#optionsContainer").hide();
    $("#mainContainer").show();
    $("#warning").show();
}

function setupOptions() {
	$("#optionsLocation").data("location", moFSSI);
	$("#optionsLocation").val(moLocation);
	MetOffice.locations.getLocList(function(data){
		$("#optionsLocation").locsearch(doSelection, true, false, true, false);
	});
    
    $("#optionsCancel").click(showMain);
	$("#optionsForecastSelectionCancel").click(resetSelectionPanel);
    $("#optionsSave").unbind("click").click(saveOptions);
    $("#optionsLanguage option").remove();
	$.ajax({url: "/public/pws/components/lib/data/language/languages.txt", 
		method: "GET",
		dataType: "json",
		async: false,
		success: function(data) {
            for (var i = 0; i < data.length; i++) {
                $("<option>").attr("value", data[i].code).html(data[i].name).appendTo("#optionsLanguage");
            }
            $("#optionsLanguage option[value=" + requiredLanguage + "]").attr("selected", "selected");
		},
        failure: function() {
            alert("There was a problem loading language: " + language);
        },
		timeout: 15000, 
        cache: true
	});
}

function doSelection(obj) {
	$("#optionsForecastSelectionPanel").show();
	var locations = MetOffice.locations.getNNearest(obj.l, obj.g, 5, MetOffice.locations.list);
	$("#optionsForecastSelectionPanel ul").html("");
	for (var i = 0; i < locations.length; i++) {
		//TODO: i18n this
		$("<li>").text(locations[i].n + " (" + Math.floor(locations[i].dist * 10) / 10 + "mi)")
			.data("id", locations[i].i)
			.data("name", locations[i].n)
			.click(chooseForecastLocation)
			.hover(function(){ $(this).addClass("hover")},function() {$(this).removeClass("hover")})
			.appendTo("#optionsForecastSelectionPanel ul");
	}
	function chooseForecastLocation() {
		$("#optionsLocation").data("location", $(this).data("id"));
		$("#optionsLocation").val($(this).data("name"));
		resetSelectionPanel();
	}
}

function resetSelectionPanel() {
	$("#optionsForecastSelectionPanel").hide();
	$("#optionsForecastSelectionPanel li").html("");
}

function saveOptions() {
    requiredLanguage = $("#optionsLanguage option:selected").val();
	moFSSI = $("#optionsLocation").data("location");
	//TODO: set moLocation to be forecast location name
	
//    moLocation = $("#optionsLanguage option:selected").val();
	$.cookie("moLanguage", requiredLanguage);
    showMain();
    setupLanguage(requiredLanguage);
    loadComponent();
}

function capitalise(input) {
    var pattern = /(\w)(\w*)/; // a letter, and then one, none or more letters 
    var a = input.split(/\s+/g); // split the sentence into an array of words

    for (i = 0 ; i < a.length ; i ++ ) {
        var parts = a[i].match(pattern); // just a temp variable to store the fragments in.
        var firstLetter = parts[1].toUpperCase();
        var restOfWord = parts[2].toLowerCase();
        a[i] = firstLetter + restOfWord; // re-assign it back to the array and move on
    }
    return a.join(' '); // join it back together
}

function resizeText() {
	$("#location span").css("font-size", maxFontSize + "px");
	var currentWidth = $("#location span").width();
	var newFontSize = (desiredWidth / currentWidth) * maxFontSize;
	$("#location span").css("font-size", ((newFontSize > maxFontSize) ? maxFontSize: newFontSize) + "px");
}

function internationalDate(englishDate) {
    var day = englishDate.substring(0,3);
    var date = englishDate.substring(4,6);
    var month = englishDate.substring(7,10);
    var year = englishDate.substring(11,13);

    return labels.calendar.day[day] + " " + date + " " + labels.calendar.month[month] + " " + year;
}

function internationalDirection(bearing) {
    var output = "";
    for (var i = 0; i < bearing.length; i++) {
        output += labels.direction[bearing.charAt(i)];
    }
    return output;
}


