﻿/*
    Copenhagen Software
    Copyright 2009
    
    EnergyMap Technology Selector Utility Functions
*/

registerArrayContainsMethod(); 

function InitializeTechnologySelector(technologyBox, areasBox, urlToGetAreasMap, populateBoxes, selectedTechnologyIds) {

	var technologyAreas = $.getJSON(urlToGetAreasMap, function(areas) {
		if (populateBoxes) {
			populateAreasBox(areasBox, areas);
		}

		var maps = buildAreasMap(areas);
		var areasMap = maps.AreasMap;
		var technologyMap = maps.TechnologiesMap;
		registerListBoxEvents(technologyBox, areasBox, areasMap);
		if (selectedTechnologyIds && selectedTechnologyIds.length > 0)
			selectTechnologies(technologyBox, areasBox, selectedTechnologyIds, areasMap, technologyMap);
	});
}

function populateAreasBox(areasBox, areas) {
    //To avoid having the SELECT resize when items are added and removed (in IE) we remember the current width and restore upon completion of this method.
    areasBox.data("origWidth", areasBox.css("width"));
    
    var options = new Array();
    for (var i = 0; i < areas.length; i++) {
        options[options.length] = technologyToOption(areas[i], false);
    }
    areasBox.html(options.join(''));

    areasBox.css("width", areasBox.data("origWidth"));
}

function selectTechnologies(technologyBox, areasBox, selectedTechnologyIds, areasMap, technologiesMap) {

	var selectedAreas = new Array();
	for (var i = 0; i < selectedTechnologyIds.length; i++) {
		selectedAreas[i] = technologiesMap[selectedTechnologyIds[i]];
	}

	areasBox.find('option').each(function(index, elmt) {
		if (selectedAreas.contains(parseInt($(elmt).attr('value')))) {
			$(elmt).attr('selected', 'selected');
		}
	});

	updateTechnologyListBox(technologyBox, areasBox, areasMap);

	technologyBox.find('option').each(function(index, elmt) {
		if (selectedTechnologyIds.contains(parseInt($(elmt).attr('value')))) {
			$(elmt).attr('selected', 'selected');
		}
	});
}

function buildAreasMap(technologyAreas)
{
    var areasMap = new Array();
    var technologyMap = new Array();
    
    for(var i = 0; i < technologyAreas.length; i++) {
    	areasMap[technologyAreas[i].Id] = technologyAreas[i].Technologies;
    	for (var j = 0; j < technologyAreas[i].Technologies.length; j++) {
    		technologyMap[technologyAreas[i].Technologies[j].Id] = technologyAreas[i].Id;
    	}
    }
	
	return { AreasMap: areasMap, TechnologiesMap: technologyMap };
}

function registerListBoxEvents(technologyBox, technologyAreaBox, areasMap)
{
    technologyAreaBox.change(function() {
        updateTechnologyListBox(technologyBox, technologyAreaBox, areasMap);
	});
}

function updateTechnologyListBox(technologyBox, technologyAreaBox, areasMap) {

    //To avoid having the SELECT resize when items are added and removed (in IE) we remember the current width and restore upon completion of this method.
    technologyBox.data("origWidth", technologyBox.css("width"));

    var areaIds = getSelectedTechnologyAreaIds(technologyAreaBox);
    var selectedIds = getSelectedTechnologyIds(technologyBox);

    var options = new Array();
    for (var i = 0; i < areaIds.length; i++) {
        var technologies = areasMap[areaIds[i]];
        for (var j = 0; j < technologies.length; j++) {
            options[options.length] = technologyToOption(technologies[j], selectedIds.contains('' + technologies[j].Id)); //The selectedIds array contains strings but the technologies[j].Id is an int, so we convert to string using ''+
        }
    }

    ///Insert options into technologyBox
    technologyBox.html(options.join(''));
    ///For some reason, sometimes the displayed values of technologyBox are only updated when the technologyBox receives focus or there's an onmouseover event on it or something.
    technologyBox.focus();

    technologyBox.css("width", technologyBox.data("origWidth"));
}

function getSelectedTechnologyIds(technologyListBox) {
    ///If nothing is selected, the previous call to val() will return null, but for consistency we want to consider this as an empty array
    var technologies = technologyListBox.val();
    if (technologies === null)
        return new Array();
    return technologies;
}

function getSelectedTechnologyAreaIds(technologyAreaListBox) {
    ///If nothing is selected, the previous call to val() will return null, but for consistency we want to consider this as an empty array
    var areaIds = technologyAreaListBox.val();
    if (areaIds === null)
        return new Array();
    return areaIds;
}

function technologyToOption(technology, selected) {
    return toOption(technology.Id, technology.Name, selected);
}

function toOption(value, text, selected) {
    var selectedStr = selected ? " selected " : "";
    return '<option value="' + value + '" ' + selectedStr + '>' + text + '</option>';
}

function registerArrayContainsMethod() {
    if (!Array.prototype.contains) {
        Array.prototype.contains = function(obj) {
            var len = this.length;
            for (var i = 0; i < len; i++) {
                if (this[i] === obj) { return true; }
            }
            return false;
        };
    }
}