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

/// Following the Java conventions, the namespace for the tomtom HD Traffic service is com.tomtom.
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.RoadNumbers
if (com.tomtom.RoadNumbers) throw new Error("com.tomtom.RoadNumbers already exists");
else com.tomtom.RoadNumbers = {};

(function() {
    
    var default_road_number_pattern = /^([A-Za-z]*) *([0-9]+)([^0-9 \(][^ ]*){0,1} *(\( *([^ ]*) *\)){0,1}/

    function createPatternFuncion(pattern, noCase) {
        return function(road) {
            var m = pattern.exec(road)
            if (m == null) return {category: road}
            rv = {category: m[1], number: m[2], subcategory: m[5]}
            if (rv.category == '') rv.category = null;
            if (rv.category != null && noCase) rv.category = rv.category.toUpperCase();
            if (rv.number == '') rv.number = null;
            if (rv.number != null) rv.number = parseInt(rv.number, 10)
            if (rv.subcategory == '') rv.subcategory = null;
            if (rv.subcategory != null && noCase) rv.subcategory = rv.subcategory.toUpperCase();
            return rv;
        }
    }

    function mapCategory(category, id) {
        if (typeof category == 'object') {
            if (category[id] != null) {
                return category[id]
            } else if (category[''] != null) {
                return category['']
            }
        }
        return category
    }

    function arraze(a) {
        if (typeof a == 'object' && a.constructor == Array) return a
        return [a]
    }

    function objectize(o) {
        if (!o) return {}
        if (typeof o == 'object') return o
        return {'': o}
    }

    function cat2(obj, order, categories) {
        var objs = arraze(obj)
    }

    function categoryArray(arr) {
        var categories = {names: [], order: []}
        for (var a = 0; a < arr.length; ++a) {
            var objs = arraze(arr[a])
            var name = objs[0]
            categories.order[a] = {}
            for (var i = 0; i < objs.length; ++i) {
                if (typeof objs[i] == 'object') {
                    if (objs[i].category) {
                        var cats = arraze(objs[i].category)
                        var dogs = arraze(objs[i].subcategory)
                        for (var j = 0; j < cats.length; ++j) {
                            categories[cats[j]] = objectize(categories[cats[j]])
                            for (var k = 0; k < dogs.length; ++ k) {
                                categories[cats[j]][dogs[k]] = a
                            }
                        }
                        categories.order[a][objs[i].category] = i;
                    }
                    if (objs[i].name) {
                        name = objs[i].name
                    }
                } else {
                    if (categories[objs[i]]) categories[objs[i]][''] = a;
                    else categories[objs[i]] = a
                    categories.order[a][objs[i]] = i;
                }
            }
            categories.names[a] = name
        }
        return categories;
    }

    function RoadNumberScheme(pattern, categories, noCase) {
        if (typeof pattern == 'function' && pattern.constructor != RegExp) {
            this.pattern = pattern
        } else {
            this.pattern = createPatternFuncion(pattern, noCase)
        }
        if (categories != null) {
            if (typeof categories == 'object' && categories.constructor == Array) {
                this.categories = categoryArray(categories)
            } else {
                this.categories = categories
            }
        } else {
            this.categories = {}
        }
    }
    com.tomtom.RoadNumberScheme = RoadNumberScheme

    function generic_compare(lhs, rhs, nullDraw) {
        nullDraw = nullDraw ? nullDraw : 1
        if (lhs == null && rhs == null) return 0;
        else if (lhs == null) return nullDraw;
        else if (rhs == null) return -1 * nullDraw;
        else return (rhs < lhs) - (lhs < rhs);
    }
    function compare(lhs, rhs) {
        var rv = generic_compare(lhs.categoryOrder, rhs.categoryOrder)
        if (rv == 0) {
            if (lhs.categoryTie != null && rhs.categoryTie != null) {
                rv = generic_compare(lhs.categoryTie, rhs.categoryTie)
            } else if (lhs.categoryOrder == null) {
                rv = generic_compare(lhs.category, rhs.category)
            }
            if (rv == 0) {
                rv = generic_compare(lhs.subcategoryOrder, rhs.subcategoryOrder, -1)
                if (rv == 0) {
                    rv = generic_compare(lhs.subcategory, rhs.subcategory, -1)
                    if (rv == 0) {
                        rv = generic_compare(lhs.number, rhs.number)
                    }
                }
            }
        }
        return rv;
    }
    
    function RoadNumbers(scheme) {
        if (scheme == null) scheme = new RoadNumberScheme(default_road_number_pattern)
        this.pattern = scheme.pattern
        this.categories = scheme.categories
        this.namedRoads = scheme.namedRoads
    }
    
    function translate(name, scheme) {
        var rv = scheme.pattern(name);
        var category = scheme.categories[rv.category]
        category = mapCategory(category, rv.subcategory)
        var subcategory = mapCategory({}, rv.subcategory)
        rv.categoryOrder = category
        rv.subcategoryOrder = subcategory
        if (rv.categoryOrder != null
            && scheme.categories.order != null
            && scheme.categories.order[rv.categoryOrder] != null
            && scheme.categories.order[rv.categoryOrder][rv.category] != null
        ) {
            rv.categoryTie = scheme.categories.order[rv.categoryOrder][rv.category]
        }
        return rv;
    }
    
    RoadNumbers.prototype.compare = function(lhs, rhs) {
        return compare(translate(lhs, this), translate(rhs, this))
    }

    RoadNumbers.prototype.category = function(name) {
        return this.translate(name).categoryOrder
    }
    RoadNumbers.prototype.translate = function(name) {
        return translate(name, this)
    }

    com.tomtom.RoadNumbers = RoadNumbers;

})();
