// TomTom HD Traffic access library, $Revision: 38755 $

var com;
if (!com) com = {};
else if (typeof com != 'object') throw new Error("com already exists and is not an object");

if (!com.tomtom) com.tomtom = {}
else if (typeof com.tomtom != 'object') throw new Error("com.tomtom already exists and is not an object");

/// Main access object is com.tomtom.Hdt
if (!com.tomtom.Hdt) throw new Error("com.tomtom.Hdt missing");

// This is fixing an orphan leak in prototype.js
/*@cc_on
  @if (@_jscript_version <= 7)
Element._getContentFromAnonymousElement = function(tagName, html) {
  var div = $('prototype-getContentFromAnonymousElement');
  if (!div) {
    div = new Element('div');
    div.id = 'prototype-getContentFromAnonymousElement';
    div.style.display = 'none';
    document.body.appendChild(div);
  }
  var t = Element._insertionTranslations.tags[tagName];
  if (t) {
    div.innerHTML = t[0] + html + t[1];
    t[2].times(function() { div = div.firstChild });
  } else div.innerHTML = html;
  return $A(div.childNodes);
};
  @end
@*/

(function() {
    var categoryMapping = {
        'ACCIDENT': '01',
        'FOG': '02',
        'DANGEROUS_CONDITIONS': '03',
        'RAIN': '04',
        'ICE': '05',
        'JAM': '06',
        'LANE_CLOSED': '07',
        'ROAD_CLOSURE': '08',
        'ROAD_WORK': '09',
        'WIND': '10',
        'FLOODING': '11',
        'DETOUR': '12',
        'CLUSTER': '13'
    };
    function findIconType(category) {
        if (!categoryMapping[category]) return '00';
        return categoryMapping[category];
    }

    // URL for an icon (on the LBS server)
    function lbsUrlGenerator(iconType, nb) {        
        return "http://lbs.tomtom.com/lbs/images/traffic/traffic-" + findIconType(iconType)
            + (nb > 1 ? '_stack' : '')
            + '.gif';
    }

    function conditionedCreate(config, createFunction, defaultInterceptor) {
        if (!config) return;
        if (typeof config == 'string') {
            config = { root: config, interceptor: defaultInterceptor }
        }
        return createFunction(config, defaultInterceptor);
    }

    function createTooltipFunction(tooltip, tooltipTemplate, element, incidents, interceptor, max) {
       return function() {
            tooltip.style.display = 'block';
            element.innerHTML = '';
            if (max == null) max = 5
            for (var i = 0; i < (incidents.length < max ? incidents.length : max); ++i) {
                var txt = ''
                if (element.innerHTML != '') {
                    txt = '<hr/>'
                }
                if (interceptor) interceptor(incidents[i]);
                txt += tooltipTemplate.evaluate(incidents[i])
                element.innerHTML += txt;
            }
            if (incidents.length > max) {
                element.innerHTML += "<hr/>..."
            }
            return tooltip;
        }
    }

    function createTooltipOutFunction(tooltip) {
        return function() {
            tooltip.style.display = 'none';
        }
    }

    function createImageCanvas(config, defaultInterceptor) {
        var tooltipTemplate
        var element
        if (config.tooltip) {
            element = $(config.tooltip)
            if (config.tooltipTemplate) {
                element = $(config.tooltipTemplate)
            }
            if (element) {
                tooltipTemplate = new Template(element.innerHTML)
            }
        }
        var tooltip = $(config.tooltip)
        delete config.tooltip
        delete config.tooltipTemplate
        config.iconHandle = config.iconHandle || function(icon) {
                var img = document.createElement('img');
                img.src = lbsUrlGenerator(icon.category, icon.incidents.incidents.length);
                img.style.bottom = '8px';
                /*@cc_on
                  @if (@_jscript_version <= 7)
                  img.style.bottom = 'auto';
                img.style.top = '8px';
                  @else
                  @end
                @*/
                img.style.right = '20px';
                img.style.position = 'relative';
                img.id = 'icon-image-' + (new Date().getTime())
                if (tooltipTemplate && tooltip) {
                    icon.incidents.incidents.sort( function(lhs, rhs) {
                        if (lhs.delaySeconds != null && rhs.delaySeconds != null)
                            return rhs.delaySeconds - lhs.delaySeconds
                        else if (lhs.delaySeconds == null && rhs.delaySeconds != null)
                            return 1;
                        else if (lhs.delaySeconds != null && rhs.delaySeconds == null)
                            return -1;
                        else if (lhs.lengthMeters != null && rhs.lengthMeters != null)
                            return rhs.lengthMeters - lhs.lengthMeters
                        else return 0;
                    } )
                    img.onmouseover = createTooltipFunction(tooltip, tooltipTemplate, 
                        element, icon.incidents.incidents,
                        config.interceptor ? config.interceptor : defaultInterceptor,
                        config.maxIncidentsPerTooltip)
                    img.onmouseout = createTooltipOutFunction(tooltip);
                }
                return img;
            }
        config.root = config.root || 'hdt-images-root'
        return config
    }

    var roadCategoryStyles = {}
    var roadNumberStyles = {}

    function limitVisibility(styles, name) {
        for (road in styles) {
            // alert(styles[road].cssText)
            com.tomtom.setCSSProperty(styles[road], 'display', name ? 'none' : null)
        }
        if (name) {
            com.tomtom.setCSSProperty(styles[name], 'display', null)
        }
    }
    com.tomtom.Hdt.prototype.limitRoadCategory = function(name) {
        limitVisibility(roadNumberStyles, null)
        limitVisibility(roadCategoryStyles, name)
    }

    com.tomtom.Hdt.prototype.limitRoadNumber = function(name) {
        limitVisibility(roadCategoryStyles, null)
        limitVisibility(roadNumberStyles, name)
    }

    function createTextCanvas(config, defaultInterceptor) {
        var element = $(config.template)
        if (!element && config.root && $(config.root).hasChildNodes()) {
            var root = $(config.root)
            while (root.hasChildNodes() && (!element || element.constructor == Text)) {
                element = root.firstChild
                root.removeChild(element)
            }
        }
        delete config.template
        if (element) {
            var template = new Template(element.innerHTML)
            config.handleIncident = config.handleIncident || function(incident) {
                if (config.interceptor) config.interceptor(incident, defaultInterceptor)
                else defaultInterceptor(incident)
                var tr = element.cloneNode(false);
                if (incident.className) {
                    com.tomtom.addClass(tr, incident.className)
                    if (!roadCategoryStyles[incident.className]) {
                        roadCategoryStyles[incident.className] = com.tomtom.getCSSStyle('.' + incident.className)
                    }
                }
                if (incident.roadNumberClass) {
                    com.tomtom.addClass(tr, incident.roadNumberClass)
                    if (!roadNumberStyles[incident.roadNumberClass]) {
                        roadNumberStyles[incident.roadNumberClass] =
                            com.tomtom.getCSSStyle('.' + incident.roadNumberClass) 
                    }
                }
                // This will leak div orphans in the original version.
                Element.insert(tr, template.evaluate(incident));
                return tr;
            }
        }
        config.root = config.root || 'hdt-incidents-root'
        return config
    }

    function createOverviewCanvas(config, defaultInterceptor, categoryNames, translator) {
        if (typeof config == 'string') {
            config = { root: config }
        }
        if (!config.interceptor) config.interceptor = defaultInterceptor
        var element = $(config.root)
        if (element == null) return function() {}
        var template = new Template(element.innerHTML)
        while(element.hasChildNodes()) {
            element.removeChild(element.firstChild);
        }
        // element.innerHTML = "";
        var roadTemplate = null;
        if (config.roadTemplate) {
            var roadElement = $(config.roadTemplate)
            if (roadElement) {
                roadTemplate = new Template(roadElement.innerHTML)
            }
        }
        return function(overview) {
            if (config.interceptor) config.interceptor(overview)
            while(element.hasChildNodes()) {
                element.removeChild(element.firstChild);
            }
            Element.insert(element, template.evaluate(overview))
            if (roadTemplate) {
                if (!overview.item) return;
                var lookup = {}
                if (categoryNames != null) {
                    var newItems = [];
                    var itemHash = {};
                    var oldItems = overview.item
                    for (var i = 0; i < oldItems.length; ++i) {
                        itemHash[overview.item[i].name] = oldItems[i];
                        oldItems[i] = 'otherRoads';
                    }
                    var otherRoads = itemHash['otherRoads']
                    if (otherRoads != null) {
                        if (otherRoads.incidents == null) otherRoads.incidents = 0;
                        for (var i = 0; i < oldItems.length; ++i) {
                            if (oldItems[i] == 'otherRoads') {
                                if (overview.item[i] != null) {
                                    if (overview.item[i].incidents) otherRoads.incidents += overview.item[i].incidents
                                    if (overview.item[i].lengthMeters) otherRoads.lengthMeters += overview.item[i].lengthMeters
                                    if (overview.item[i].delaySeconds) otherRoads.delaySeconds += overview.item[i].delaySeconds
                                }
                            }
                        }
                    }
                    for (var i = 0; i < categoryNames.length; ++i) {
                        newItems[i] = itemHash[categoryNames[i]]
                    }
                    overview.item = newItems;
                }
                for (var i = 0; i < overview.item.length; ++i) {
                    var div = roadElement.cloneNode(false);
                    if (translator && translator[overview.item[i].name]) {
                        overview.item[i].category = translator[overview.item[i].name]
                    } else {
                        overview.item[i].category = overview.item[i].name
                    }
                    Element.insert(div, roadTemplate.evaluate(overview.item[i]))
                    com.tomtom.addClass(div, overview.item[i].name)
                    element.appendChild(div)
                }
                var div = roadElement.cloneNode(false);
                if (translator && translator['total']) {
                    overview.total.category = translator['total']
                } else {
                    overview.total.category = 'total'
                }
                Element.insert(div, roadTemplate.evaluate(overview.total))
                com.tomtom.addClass(div, 'total')
                element.appendChild(div)
            }
        }
    }

    var defaultConverter = com.tomtom.Hdt.converter;

    var defaultRoadNumberer = { category: function(str) {
        if (str.charAt) {
            return str.charAt(0)
        } else {
            return null;
        }
    }}

    function incidentsInterceptor(incident, converter, roadNumberer) {
        if (incident.length) return;
        incident.length = converter.length(incident.lengthMeters)
        incident.delay = converter.time(incident.delaySeconds)
        incident.fullRoadName = null
        if (incident.roadNumber != null) {
            incident.fullRoadName = incident.roadNumber;
        }
        if (incident.roadName != null) {
            if (incident.fullRoadName != null) {
                incident.fullRoadName += ", "
            } else {
                incident.fullRoadName = ""
            }
            incident.fullRoadName += incident.roadName;
        }
        if (incident.fullRoadName == null) incident.fullRoadName = ""
        var category = roadNumberer.category(incident.roadNumber)
        incident.className = category == null ? 'other-road' : 'road-' + category
        incident.icon = '<img src="' + lbsUrlGenerator(incident.category) + '"'
        if (incident.description != null) {
          incident.icon += ' alt="' + incident.description + '"'
          incident.icon += ' title="' + incident.description + '"'
        }
        incident.icon += '/>'
    }
    function createIncidentsInterceptor(converter, roadNumberer) {
        return function(incident) { incidentsInterceptor(incident, converter, roadNumberer) }
    }

    function incidentsOverviewInterceptor(overview, converter) {
        if (overview.totalLength) return;
        overview.totalLength = converter.length(overview.totalLengthMeters);
        overview.totalDelay = converter.time(overview.totalDelaySeconds);
        overview.age = converter.time(overview.ageMs / 1000, true)
        overview.date = new Date(overview.timestamp).toLocaleString()
        if (overview.visible) {
			if (overview.visible.totalLengthMeters) {
				overview.visible.totalLength = converter.length(overview.visible.totalLengthMeters);
			}
			if (overview.visible.totalDelaySeconds) {
				overview.visible.totalDelay = converter.time(overview.visible.totalDelaySeconds);
			}
        }
    }
    function createIncidentsOverviewInterceptor(converter) {
        return function(overview) { incidentsOverviewInterceptor(overview, converter)}
    }

    function top10Interceptor(incident, converter) {
        incident.length = converter.length(incident.lengthKm * 1000)
        incident.delay = converter.time(incident.delayMin * 60)
    }
    function createTop10Interceptor(converter) {
        return function(incident) { top10Interceptor(incident, converter) }
    }

    function top10OverviewInterceptor(overview) {
        overview.date = new Date(overview.timestamp).toLocaleString();
    }
    function createTop10OverviewInterceptor(converter) {
        return top10OverviewInterceptor;
    }

    function countryOverviewInterceptor(overview, converter) {
        if (overview.date) return;
        overview.date = new Date(overview.timestamp).toLocaleString();
        if (overview.item) {
            overview.total = {delaySeconds: 0, lengthMeters: 0, incidents: 0}
            for (var i = 0; i < overview.item.length; ++i) {
                var item = overview.item[i]
                overview.item[i].delay = converter.time(item.delaySeconds);
                overview.total.delaySeconds += item.delaySeconds
                overview.item[i].length = converter.length(item.lengthMeters);
                overview.total.lengthMeters += item.lengthMeters
                overview.total.incidents += item.incidents
            }
            overview.total.delay = converter.time(overview.total.delaySeconds);
            overview.total.length = converter.length(overview.total.lengthMeters);
        }
    }
    function createCountryOverviewInterceptor(converter) {
        return function(overview) { countryOverviewInterceptor(overview, converter) }
    }

    com.tomtom.Hdt.prototype.iconUrl = function(cat) { return lbsUrlGenerator(cat, 1) }

    com.tomtom.createTemplateCanvases = function(config, locales) {
        var converter
        var roadNumberer
        var translator
        if (locales != null) {
            converter = locales.converter
            roadNumberer = locales.roadNumbers
            translator = locales.translator
        }
        if (converter == null) {
            if (com.tomtom.Hdt.converter != null) {
                converter = com.tomtom.Hdt.converter
            } else {
                converter = defaultConverter
            }
        }
        var rv = {};
        if (roadNumberer == null) roadNumberer = defaultRoadNumberer
        else rv.roadNumbering = roadNumberer
        var overview = null;
        if (config.images) {
            rv.imageCanvas = conditionedCreate(config.images,
                createImageCanvas,
                createIncidentsInterceptor(converter, roadNumberer));
        }
        if (config.incidents) {
            if (config.incidents.root) {
                rv.incidentsCanvas = conditionedCreate(config.incidents, createTextCanvas, createIncidentsInterceptor(converter, roadNumberer));
            }
            if (config.incidents.overview) {
                if (!overview) overview = {};
                if (typeof config.incidents.overview == 'function') {
                    overview.incidents = config.incidents.overview
                } else {
                    overview.incidents = createOverviewCanvas(
                        config.incidents.overview, 
                        createIncidentsOverviewInterceptor(converter)
                    );
                }
            }
        }
        if (config.top10) {
            if (config.top10.overview) {
                if (!overview) overview = {};
                overview.top10 = createOverviewCanvas(config.top10.overview, createTop10OverviewInterceptor(converter));
                delete config.top10.overview;
            }
            rv.top10Canvas = {}
            for (type in config.top10) {
                rv.top10Canvas[type] = conditionedCreate(config.top10[type], createTextCanvas, createTop10Interceptor(converter));
            }
        }
        if (config.overview) {
            if (!overview) overview = {};
            if (typeof config.overview == 'function') {
                overview.country = config.overview
            } else {
                overview.country = createOverviewCanvas(
                    config.overview,
                    createCountryOverviewInterceptor(converter),
                    config.overview.categoryNames,
                    translator
                );
            }
        }
        if (overview) rv.overview = overview;
        return rv;
    };

})();
