/* 
TODO 

X 	function with array as param
X		plot all array elements to map with correct icons and information
	
X	onclick on stop
X		find stop coordinate, and place infobox there 

X	function with map layer as param
X		add map layer and checkbox to toggle it


onclick map AND utsalgssteder and holdeplasser is visible
check which is on top to pick the right layer
		
*/

var en = false;

var trafikanten;
trafikanten =
{
    token: "m_p7rlKxOcTdajJgBBTC8IIfVISJvUkxAZMVRgZcN37ApUT87dABnPlj1xb4ts7W",

    stopEvents: function (e) {

        e.cancelBubble = true;
        e.returnValue = false;

        if (e.stopPropagation) {
            e.stopPropagation();
        }
        if (e.preventDefault) {
            e.preventDefault();
        }
    }
};

//NOTE https
function GetProtocol() {
    var gaJsHost = (("https:" == document.location.protocol) ?
                    "https://" : "http://");
    return gaJsHost;
}

trafikanten.map =
{
    MapInstance: null,
    controlPressed: false,
    inited: false, // set to true if the init function has been run
    graphics: null, // layer to draw graphics onto

    // projection
    gsvc: null,
    outSR: null,

    settings:
	{
	    MapInit: 'travelSearch',
	    MapContainer: 'mapControl',
	    MapID: 'map',

	    icons: {
	        Buss: { path: '/styles/img/map_buss.png', width: 16, height: 16 },
	        Baat: { path: '/styles/img/map_baat.png', width: 16, height: 16 },
	        Tog: { path: '/styles/img/map_tog.png', width: 16, height: 16 },
	        Trikk: { path: '/styles/img/map_trikk.png', width: 16, height: 16 },
	        Tbane: { path: '/styles/img/map_tbane.png', width: 16, height: 16 },

	        Here: { path: '/styles/img/icon_pointer_here.png', width: 64, height: 64 },

	        Start: { path: "/styles/img/icon_pointer_start.png", width: 56, height: 56 },
	        Stopp: { path: "/styles/img/icon_pointer_stop.png", width: 56, height: 56 },
	        Stop: { path: "/styles/img/icon_pointer_stop_en.png", width: 56, height: 56 },
	        WalkStart: { path: "/styles/img/icon_pointer_start_walk.png", width: 56, height: 56 },
	        WalkStopp: { path: "/styles/img/icon_pointer_stop_walk.png", width: 56, height: 56 },
	        WalkStop: { path: "/styles/img/icon_pointer_stop_walk_en.png", width: 56, height: 56 }
	    },

	    input: {
	        From: "FraSted",
	        To: "TilSted"
	    },

	    StopsClickable: true, // enables information on stops when user clicks
	    ShortcutsEnabled: true, // enables the "travel to" / "travel from" functionality
	    RealtimeEnabled: true, // enabled the "show realtime for this stop" functionality
	    LinesEnabled: true, // enabled the "show realtime for this stop" functionality
	    LinesMax: 6 // max number of lines to show
	},

    arrLayers: [],

    layers:
	{
	    //Note https
	    MapLandscape: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/GeocacheLandskap/MapServer?token=' + trafikanten.token,
	    //MapLandscape: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/Geocache_UTM33_EUREF89/GeocacheLandskap/MapServer?token=' + trafikanten.token,
	    // MapBase: 'https://www.geodataonline.no/ArcGIS/rest/services/Norge/GeoCacheBasis/MapServer'+,
	    MapBase: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/GeocacheBasis/MapServer?token=' + trafikanten.token,
	    //MapBase: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/Geocache_UTM33_EUREF89/GeocacheBasis/MapServer?token=' + trafikanten.token,
	    // MapPictures: 'https://www.geodataonline.no/ArcGIS/rest/services/Norge/GeoCacheBilder/MapServer',
	    MapPictures: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/GeocacheBilder/MapServer?token=' + trafikanten.token,
	    //MapPictures: GetProtocol() + 'cloud.geodataonline.no/ArcGIS/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer?token=' + trafikanten.token,

	    Holdeplasser: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/Holdeplasser/MapServer',

	    Utsalgssteder: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/SaleZone/MapServer',
	    Takstsoner_label: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/SaleZone/MapServer',
	    Takstsoner: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/SaleZone/MapServer'

	},

    services:
	{
	    //Note https
	    Geometry: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/Geometry/GeometryServer',
	    Route: GetProtocol() + 'kart.trafikanten.no/ArcGIS/rest/services/route/NAServer/Route',
	    Trip: GetProtocol() + 'services.trafikanten.no/Trip/GetTrip/',
	    ClosestByCoordinate: GetProtocol() + 'services.trafikanten.no/Place/GetClosestStopsByCoordinates/',
	    GetLines: GetProtocol() + 'services.trafikanten.no/Place/GetLines/',
	    IsValidPlace: GetProtocol() + 'services.trafikanten.no/RealTime/IsValidPlace/',
	    FindMatches: GetProtocol() + 'services.trafikanten.no/RealTime/FindMatches/'
	},

    loadDojoPackages: function () {
        dojo.require('esri.map');
        dojo.require('esri.tasks.query');
        dojo.require('esri.tasks.gp');
        dojo.require('esri.tasks.route'); // brukt av gangtrase
        dojo.require('esri.tasks.geometry'); // brukt til å prosjektere koordinater
        dojo.require("dojo.DeferredList");
        dojo.require("esri.layers.FeatureLayer");
    },

    init: function () {
        // Prevent loading if this page does not contain a map
        if ($("." + trafikanten.map.settings.MapInit).length == 0) { return false; }

        // Prevent more than one initialization 
        if (trafikanten.map.inited === false) {
            trafikanten.map.inited = true;
        } else {
            return false;
        }

        // Load all dependencies
        trafikanten.map.loadDojoPackages();

        // Config for the zoom slider
        esriConfig.defaults.map.slider = { left: '25px', top: '100px', height: '200px' };

        // Set default extent
        var ext = new esri.geometry.Extent(240000, 6640000, 270000, 6660000, new esri.SpatialReference({ wkid: 32633 }));

        var infoWindow = new myModules.InfoWindow({
            domNode: dojo.create("div", null, dojo.byId("map"))
        });

        var mapId = trafikanten.map.settings.MapID;
        trafikanten.map.MapInstance = new esri.Map(mapId, { logo: false, nav: false, extent: ext, infoWindow: infoWindow });

        // Add map layer
        var baseLayer = new esri.layers.ArcGISTiledMapServiceLayer(trafikanten.map.layers.MapBase);
        dojo.connect(baseLayer, 'onError', trafikanten.map.callback.errorHandler);
        var pictureLayer = new esri.layers.ArcGISTiledMapServiceLayer(trafikanten.map.layers.MapPictures);
        dojo.connect(pictureLayer, 'onError', trafikanten.map.callback.errorHandler);
        var landscapeLayer = new esri.layers.ArcGISTiledMapServiceLayer(trafikanten.map.layers.MapLandscape);
        dojo.connect(landscapeLayer, 'onError', trafikanten.map.callback.errorHandler);

        trafikanten.map.addLayer("Vektor", baseLayer, false, true);
        trafikanten.map.addLayer("Bilde", pictureLayer, false);
        trafikanten.map.addLayer("Landskap", landscapeLayer, false);


        // trafikanten.map.gsvc = new esri.tasks.GeometryService(trafikanten.map.services.Geometry);
        // trafikanten.map.outSR = new esri.SpatialReference({ wkid: 32633 });


        // Add scaling details; updated when the view changes
        $("#" + mapId).append("<div class='scaleDetails'><div class='scaleDetailsContent'></div></div>");
        dojo.connect(trafikanten.map.MapInstance, "onExtentChange", function (extent, delta, outLevelChange, outLod) {
            var len = (outLod.scale / 100);
            var unit = "m";
            if (len > 5000) {
                len /= 1000;
                unit = "km";
            }
            $("#" + mapId + " .scaleDetailsContent").html("<span class='len'>" + len + unit + "</span><span class='scale'>1: " + outLod.scale + "</span>");

            $("#" + mapId).bind("contextmenu", function (e) {
                return false;
            });

        });

        // Update settings and display the map
        trafikanten.map.show();

        // When map is loaded, do this;
        dojo.connect(trafikanten.map.MapInstance, 'onLoad', function (map) {

            // Place it and resize it
            map.reposition();
            map.resize();


            // Initialize the identify stop task
            trafikanten.map.query.initIdentifyTask();

            // Gangtrase initialisering
            trafikanten.map.route.initRouteQuery();

            // run custom initialization - like plotting items or changing layers
            trafikanten.map.customInit();
        });

        // Register keypresses
        $(document).keydown(trafikanten.map.events.onKeyDown);
        $(document).keyup(trafikanten.map.events.onKeyUp);
    },

    // placeholder for a custom initializing function 
    customInit: function () {
    },

    // add a layer ot the mix
    addLayer: function (layerName, layer, overlay, visible, index) {
        trafikanten.map.arrLayers[layerName] = { layer: layer, overlay: overlay };
        if (index) {
            trafikanten.map.arrLayers[layerName].index = index;
        }
        if (!overlay && visible) {
            trafikanten.map.arrLayers[layerName]['visible'] = true;
            trafikanten.map.MapInstance.addLayer(layer, 0);
        }
        else if (overlay) {
            trafikanten.map.arrLayers[layerName]['visible'] = false;
            var mapLayers = $("#" + trafikanten.map.MapInstance.id + " .mapLayers");

            if (mapLayers.length == 0) {
                $("#" + trafikanten.map.MapInstance.id).append("<div class='mapLayers'></div>");
            }
            var input = $("#" + trafikanten.map.MapInstance.id + " .mapLayers").append("<label for='" + layerName + "'><input onclick='trafikanten.map.toggleLayer(\"" + layerName + "\");' type='checkbox' name='" + layerName + "' id='" + layerName + "'> " + layerName + "</label>");
            if (visible) {
                trafikanten.map.toggleLayer(layerName);
                input.find("#" + layerName).attr("checked", "checked");
            }
        }
    },

    // swap between non overlay layers
    changeLayer: function (el, layerName) {
        $("#" + trafikanten.map.MapInstance.id + " .mapTypes .selected").removeClass("selected");
        $(el).addClass("selected");

        var layer = trafikanten.map.arrLayers[layerName];
        if (layer.overlay) {
            return;
        }
        if (trafikanten.map.MapInstance.layerIds[0]) {
            trafikanten.map.MapInstance.removeLayer(trafikanten.map.MapInstance.getLayer(trafikanten.map.MapInstance.layerIds[0]));
        }
        if (layer.layer) {
            trafikanten.map.MapInstance.addLayer(layer.layer, 0);
        }
    },

    // toggles an overlay layer on / off
    toggleLayer: function (layerName) {
        var layer = trafikanten.map.arrLayers[layerName];
        if (!layer.overlay) {
            return;
        }
        if (!layer.visible) {
            layer.visible = true;
            if (layer.index) {
                trafikanten.map.MapInstance.addLayer(layer.layer, layer.index);
            } else {
                trafikanten.map.MapInstance.addLayer(layer.layer);
            }
        } else {
            layer.visible = false;
            trafikanten.map.MapInstance.removeLayer(layer.layer);
        }
    },

    mapShowMenu: function (map, navn, content, evt, point) {
        var p = evt.screenPoint;
        if (point) {
            p = point;
        }

        map.infoWindow.setTitle(navn);
        map.infoWindow.setContent(content);
        map.infoWindow.show(p, map.getInfoWindowAnchor(p));

        // console.log(p);
        /*
        // hack to set the height of the infowindow to fill the content
        var contentHeight = 0;
        contentHeight += $(".infowindow .user .titlebar").height();
        contentHeight += 7; // padding top
        contentHeight += 6; // border
		
        var ul = $(".infowindow .user .content ul");
        if(ul.length > 0){
        contentHeight += ul.height() + 15;
        }
        // console.log(contentHeight);
        // contentHeight = Math.max(contentHeight, 30);
        map.infoWindow.resize(195, contentHeight);
        */
    },

    hideMenu: function () {
        if (trafikanten.map.MapInstance.infoWindow) {
            trafikanten.map.MapInstance.infoWindow.hide();
        }
    },



    loadCoordinate: function (x, y, map) {
        if (!map) {
            if (!trafikanten.map.MapInstance) {
                trafikanten.map.init();
            }
            map = trafikanten.map.MapInstance;
        }


        if (!x || !y || x == 0 || y == 0) {
            $('#' + map.id + ' .mapResult').html('Mangler gyldige koordinater.');
            return;
        }

        var point = { 'geometry': { 'x': x, 'y': y, 'spatialReference': { 'wkid': 32632}} };
        trafikanten.map.query.projectCoordinate(point, map);
    },

    focusOnStop: function (stopPoint, map, callBack) {
        if (!map) {
            map = trafikanten.map.MapInstance;
        }

        // map.extent = map.extent.centerAt(stopPoint);
        // map.setLevel(12);

        map.centerAndZoom(stopPoint, 13); // causes bugs with dynamic layers
        // console.log(stopPoint);

        /*
        // method 1 - center, then zoom
        map.centerAt(stopPoint);
		
        map.onPanEnd = function(extent, endPoint) 
        {
        map.onPanEnd = function(){};
        setTimeout(function(){
        map.setLevel(12);
        }, 200);
        };
        */

        /*
        // method 2 - zoom, then center
        // map.setLevel(12);
        // map.onZoomEnd = function(extent, zF, anchor, level){
        // map.centerAt(stopPoint);
        // };
        */

        trafikanten.map.plotCoordinate(stopPoint.x, stopPoint.y, trafikanten.map.settings.icons.Here);


        map.resize();
        map.reposition();

        if (typeof callBack == "function") {
            //console.log("callback");
            callBack();
        }
    },









    newMap: function ($this, obj, url) {
        trafikanten.map.loadDojoPackages();

        var match = new RegExp("x(\\d{6,7})y(\\d{6,7})", "i").exec($this.attr('class'));
        var coords = [];
        if (match) {
            coords = [match[1], match[2]];
        }

        // Add the map
        var mapid = "map" + (new Date()).getTime();
        // console.log(mapid+","+travelRoute);
        var html = "<div class='" + trafikanten.map.settings.MapContainer + "'><div class='mapTypes'><a href='" + url + "' class='maximize'><span></span></a></div><div id='" + mapid + "' class='tundra'></div><div class='mapResults'></div></div>";
        var extent = new esri.geometry.Extent({ 'xmin': 240000, 'ymin': 6640000, 'xmax': 270000, 'ymax': 6660000, spatialReference: { wkid: 32633} });
        var options = {
            showInfoWindowOnClick: false,
            nav: false,
            slider: false,
            extent: extent
        };

        obj.html(html);

        var map = new esri.Map(mapid, options);

        var pictureLayer = new esri.layers.ArcGISTiledMapServiceLayer(trafikanten.map.layers.MapBase);
        map.addLayer(pictureLayer);
        //dojo.connect(pictureLayer, 'onError', trafikanten.map.callback.errorHandler);

        var hplLayer = new esri.layers.ArcGISDynamicMapServiceLayer(trafikanten.map.layers.Holdeplasser);
        map.addLayer(hplLayer);
        //dojo.connect(hplLayer, 'onError', trafikanten.map.callback.errorHandler);

        dojo.connect(map, 'onLoad', function () {
            if (coords.length) {
                trafikanten.map.loadCoordinate(coords[0], coords[1], map);
            }
            // Disable context menu on the map
            $("#" + mapid).bind("contextmenu", function (e) {
                return false;
            });

            // Update settings and display the map
            $("#" + mapid).parent().show();


            if (!$.browser.msie) {
                // console.log(obj);
                obj.slideDown("fast", function () {
                    // Reset map position and size
                    map.reposition();
                    map.resize();

                }).addClass("expanded");
            } else {
                obj.addClass("expanded").show();

                // Reset map position and size
                map.reposition();
                map.resize();

            }
        });
    },

    plotCoordinate: function (x, y, icon, map) {
        if (!map) {
            if (!trafikanten.map.MapInstance) {
                trafikanten.map.init();
            }
            map = trafikanten.map.MapInstance;
        }
        // console.log("Plotting stops");
        var layer, symbol, point, graphic;

        // layer = new esri.layers.GraphicsLayer();
        symbol = new esri.symbol.PictureMarkerSymbol(icon.path, icon.width, icon.height);
        if (icon.xoffset) {
            symbol.xoffset = icon.xoffset;
        }
        if (icon.yoffset) {
            symbol.yoffset = icon.yoffset;
        }

        point = new esri.geometry.Point(x, y, new esri.SpatialReference({ wkid: 32633 }));
        graphic = new esri.Graphic(point, symbol);

        map.graphics.clear();
        map.graphics.add(graphic);


        // map.addLayer(layer);
    },

    plotItems: function (items, icon, template, map) {
        /*
        Items: array of objects
        name: string
        attributes: array
        X: int
        Y: int
        icon: 
        path: string - path to icon
        width: int
        height: int
        template: string template // "${NAME}<br />Arrival: ${ATIME}<br />Departure: ${DTIME}<br />${BALLOWED} ";
        map: referance to map
			
			
        */
        if (!map) {
            if (!trafikanten.map.MapInstance) {
                trafikanten.map.init();
            }
            map = trafikanten.map.MapInstance;
        }
        // console.log("Plotting stops");
        var layer, outSR, symbol;

        layer = new esri.layers.GraphicsLayer();
        symbol = new esri.symbol.PictureMarkerSymbol(icon.path, icon.width, icon.height);
        if (icon.yoffset) {
            symbol.yoffset = icon.yoffset;
        }

        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            var point = new esri.geometry.Point(item.X, item.Y, new esri.SpatialReference({ wkid: 32633 }));
            var graphic = new esri.Graphic(point, symbol);
            graphic.setAttributes(item.attributes);
            // console.log(gsvc);
            // trafikanten.map.gsvc.project([graphic], outSR, function(features) {
            // var g = features[0];
            graphic.setInfoTemplate(new esri.InfoTemplate(item.name, template));
            // console.log(point);
            layer.add(graphic);
            // });
        }
        // console.log("ah");

        return layer;
        //trafikanten.map.addLayer(title, layer, true, visible);
        // map.addLayer(layer);
    },


    clearGraphics: function (map) {
        if (!map) {
            map = trafikanten.map.MapInstance;
        }
        $("#" + map.id + ' .mapResult').html('');
        if (map.graphics) {
            map.graphics.clear();
            // console.log("cleared graphics");
        }
    },

    hide: function () {
        $('.mapControl').css({ display: 'none' });
    },

    show: function () {

        $('.mapControl').css({ display: 'block' });
    }
};

trafikanten.map.events =
{
    dynamicHouseLink: function (element) {
        var coords = [];

        var match = new RegExp("x(\\d{6,7})y(\\d{6,7})", "i").exec($(element).attr('class'));

        if (match) {
            coords = [match[1], match[2]];
        }

        $('.mapControl').width($('.mapControl').parent().width());

        trafikanten.map.show();
        trafikanten.map.load(0);

        trafikanten.map.loadCoordinate(coords[0], coords[1]);
    },

    handleContextMenuClick: function (linkElement) {
        var urlAction = $(linkElement).attr('href');

        $.get(
            urlAction,
            '',
            function (data, textStatus) {
                $('#rightajaxUpdateArea').html(data);
            }
        );
    },

    mapOnClick: function (event) {
        //console.log(event);
        if (((!trafikanten.map.settings.StopsClickable || !trafikanten.map.arrLayers['Stoppesteder'].visible) && !trafikanten.map.arrLayers['Utsalgssteder'].visible)) return;

        trafikanten.map.query.doIdentifyTask(trafikanten.map.MapInstance, event, false);
        return false;
    },
    mapOnMouseDown: function (event) {
        if (((!trafikanten.map.settings.StopsClickable || !trafikanten.map.arrLayers['Stoppesteder'].visible) && !trafikanten.map.arrLayers['Utsalgssteder'].visible)) return;

        if (event.button == dojo.mouseButtons.RIGHT || (trafikanten.map.controlPressed && event.button == dojo.mouseButtons.LEFT)) {
            trafikanten.map.query.doIdentifyTask(trafikanten.map.MapInstance, event, true);
        }
        return false;
    },

    onKeyDown: function (e) {
        //console.log("DOWN "+e.keyCode );
        if (e.keyCode && e.keyCode == 17) {
            trafikanten.map.controlPressed = true;
        }
    },
    onKeyUp: function (e) {
        //console.log("UP "+e.keyCode );
        if (e.keyCode && e.keyCode == 17) {
            trafikanten.map.controlPressed = false;
        }
    },

    delayedAlign: function () {
        var timer;

        clearTimeout(timer);

        timer = setTimeout(trafikanten.map.events.reAlignMap, 500);
    },

    reAlignMap: function () {
        trafikanten.map.MapInstance.resize();
        trafikanten.map.MapInstance.reposition();
    }
};

trafikanten.map.callback =
{
    showSymbols: function (results) {
        trafikanten.map.clearGraphics();

        if (results && results.features.length > 0) {
            var feature = results.features[0]; //Always expects only one. Holdeplass is identified on Nummer = <id>

            var symbol = new esri.symbol.SimpleMarkerSymbol('o', 35, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([0, 204, 51, 1]), 3), new dojo.Color([0, 0, 0, 0]));
            //            var text = "";

            //            for (att in feature.attributes)
            //            {
            //                text = text + "<b>" + att + ":</b>  " + feature.attributes[att] + "<br />";
            //            }

            if (trafikanten.map.MapInstance.graphics) {
                // Project 
                var point = new esri.geometry.Point(feature.geometry.x, feature.geometry.y, new esri.SpatialReference({ wkid: 32632 }));
                var graphic = new esri.Graphic(point, null);
                var gsvc = new esri.tasks.GeometryService(trafikanten.map.services.Geometry);
                gsvc.project([graphic], outSR, function (features) {
                    stopsLayer.add(new esri.Graphic(features[0].geometry, symbol));
                    // var scp = map.toScreen(features[0].geometry);
                    // map.infoWindow.show(scp,map.getInfoWindowAnchor(scp));
                    trafikanten.map.focusOnStop(features[0].geometry);
                });

            }

            if (!feature.geometry) {
                //                text = "Ingen treff for holdeplass i kart";
                //                $('#mapResult').html(text);
                $('#' + map.id + ' .mapResult').html('Ingen treff for holdeplass i kart.');
            }
        }
        else {
            $('#' + map.id + ' .mapResult').html('Ingen treff for holdeplass i kart');
        }
    },
    identifyComplete: function (results, evt, rightClick, map) {
        if (!map) {
            map = trafikanten.map.MapInstance;
        }
        //console.log("done");
        //trafikanten.map.clearGraphics(map);
        var content = "";

        if (results.length > 0) {
            // console.log(results);

            var bothVisible = trafikanten.map.arrLayers['Stoppesteder'].visible && trafikanten.map.arrLayers['Utsalgssteder'].visible;
            var bothHasData = results[0][1].length > 0 && results[1][1].length > 0;
            var index = 0;

            // hack to check which is on top, and give the proper info
            if (bothVisible && bothHasData) {
                for (var i = 0; i < map.layerIds.length; i++) {
                    var layer = map.getLayer(map.layerIds[i]);
                    var stopLayer = trafikanten.map.arrLayers['Stoppesteder'];
                    var saleLayer = trafikanten.map.arrLayers['Utsalgssteder'];
                    if ((stopLayer.layer == layer || saleLayer.layer == layer) && index == 0) {
                        index++;
                        continue;
                    }

                    if (stopLayer.layer == layer && index == 1) {
                        trafikanten.map.stop.buildMenuForStop(results[0][1], evt, map);
                        return;
                    } else if (saleLayer.layer == layer && index == 1) {
                        trafikanten.map.stop.buildMenuForSalepoint(results[1][1], evt, map);
                        return;
                    }

                }
            } else if (results[0][1].length > 0 && trafikanten.map.arrLayers['Stoppesteder'].visible) {
                trafikanten.map.stop.buildMenuForStop(results[0][1], evt, map);
            }
            else if (results[1][1].length > 0 && trafikanten.map.arrLayers['Utsalgssteder'].visible) {
                trafikanten.map.stop.buildMenuForSalepoint(results[1][1], evt, map);
            }
        }
    },

    getClosestStopsComplete: function (results, evt) {
        trafikanten.map.clearGraphics();

        if (results.length > 0 && (results.length <= trafikanten.map.query.MaxCount || trafikanten.map.query.RetryCount > trafikanten.map.query.MaxRetry)) {
            // Show symbol
            var map = trafikanten.map.MapInstance;
            //var symbol = new esri.symbol.SimpleMarkerSymbol('*', 10, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([255, 0, 0, 1]), 3), new dojo.Color([0, 0, 0, 0]));

            // Build context-menu
            var hplId = results[0].feature.attributes['Nummer'];
            var navn = results[0].feature.attributes['Navn'];
            var type = results[0].feature.attributes['Type_'];

            trafikanten.map.stop.buildMenu(hplId, navn, map, evt, results[0].feature.geometry);
        }
        else {
            // adjust tolerance and extent
            trafikanten.map.query.doClosestStopsQuery(trafikanten.map.MapInstance, evt, results.length);
        }
    },

    onProjectCompleted: function (features) //On Completed convertion of coordinates
    {
        trafikanten.map.clearGraphics();

        if (features && features.length > 0) {
            var point = features[0].geometry;

            // Remove comments to get the green circle symbol back

            // var symbol = new esri.symbol.SimpleMarkerSymbol('o', 35, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([0, 204, 51, 1]), 3), new dojo.Color([0, 0, 0, 0]));
            var symbol = new esri.symbol.PictureMarkerSymbol(trafikanten.settings.icons.Here.path, trafikanten.settings.icons.Here.width, trafikanten.settings.icons.Here.height);

            if (trafikanten.map.MapInstance.graphics) {
                trafikanten.map.MapInstance.graphics.add(new esri.Graphic(point, symbol));
            }

            //trafikanten.map.query.findClosestStopByCoordinate(point, trafikanten.map.MapInstance);

            trafikanten.map.focusOnStop(point);
        }
        else {
            $('#' + trafikanten.map.settings.MapID + ' .mapResult').html('Husnummeret ble ikke funnet.');
        }
    },

    //Displays any error returned by Task
    errorHandler: function (err) {
        //console.log('Error' + err + '<end>');
        $('#' + trafikanten.map.settings.MapID + ' .mapResult').html('Feil under lasting av kart');
        //alert("An error occured\n" + err.message + "\n" + err.details.join("\n"));
    },

    //Displays any error returned by Task
    errorHandlerTrafikanten: function (err) {
        //console.log('Error' + err + '<end>');
        $('#' + trafikanten.map.settings.MapID + ' .mapResult').html('Feil under lasting av kart');
        //alert("An error occured\n" + err.message + "\n" + err.details.join("\n"));
    }
};


trafikanten.map.route =
{
    routeObject: null,
    stopSymbol: null,
    routeSymbol: null,
    routeLayer: null,
    directions: null,
    directionFeatures: null,
    segmentGraphic: null,

    initRouteQuery: function () {

        var queryObject = {};
        queryObject.Task = new esri.tasks.RouteTask(trafikanten.map.services.Route);
        queryObject.Query = new esri.tasks.RouteParameters();

        queryObject.Query.impedanceAttribute = "Minutes";
        queryObject.Query.restrictionAttributes = [];
        queryObject.Query.useHierarchy = false;
        queryObject.Query.ignoreInvalidLocations = true;
        queryObject.Query.restrictUTurns = "esriNFSBAllowBacktrack";
        queryObject.Query.outSpatialReference = new esri.SpatialReference({ wkid: 32633 });
        // queryObject.Query.outSR = "32633";
        queryObject.Query.findBestSequence = false;
        queryObject.Query.useTimeWindows = false;
        queryObject.Query.preserveFirstStop = true;
        queryObject.Query.preserveLastStop = true;
        queryObject.Query.outputLines = "esriNAOutputLineTrueShapeWithMeasure";

        queryObject.Query.directionsLanguage = en ? "en-US" : "no-NO"; //kart5 & kart6: "no-NO";
        // queryObject.Query.directionsLanguage = "nb_NO"; //kart5 & kart6: "no-NO";
        queryObject.Query.directionsLengthUnits = "esriNAUMeters";
        queryObject.Query.directionsTimeAttribute = "Minutes";

        queryObject.Query.returnBarriers = false;
        queryObject.Query.returnDirections = true;
        queryObject.Query.returnRoutes = true;
        queryObject.Query.returnStops = false;


        queryObject.Query.stops = new esri.tasks.FeatureSet(); //{"features":[{"geometry":{"x":260489.68580137176,"y":6649917.191965352},"attributes":{"address":"Stopp # 0"}},{"geometry":{"x":262085.12649225313,"y":6650663.318457604},"attributes":{"address":"Stopp # 1"}}]});

        trafikanten.map.query.loadErrorHandler(queryObject.Task);

        trafikanten.map.route.routeObject = queryObject;

        trafikanten.map.route.routeSymbol = new esri.symbol.SimpleLineSymbol().setColor(new dojo.Color([0, 0, 255, 0.5])).setWidth(5);

    },

    parseRouteWithPoints: function (pA, pB) {
        var inSR = new esri.SpatialReference({ wkid: 32632 });
        var pointA = new esri.geometry.Point(pA[0], pA[1], inSR);
        var pointB = new esri.geometry.Point(pB[0], pB[1], inSR);

        trafikanten.map.route.projectRoute(pointA, pointB);
    },

    projectRoute: function (from, to) {
        var gsvc = new esri.tasks.GeometryService(trafikanten.map.services.Geometry);
        var outSR = new esri.SpatialReference({ wkid: 32633 });
        var ptA = null;
        var ptB = null;

        gsvc.project([new esri.Graphic(from, null)], outSR, function (features) {
            ptA = features[0].geometry;
            trafikanten.map.route.routeObject.Query.stops.features.push(new esri.Graphic(ptA, null, { name: $("#FraSted").val() }));
            gsvc.project([new esri.Graphic(to, null)], outSR, function (features) {
                ptB = features[0].geometry;
                trafikanten.map.route.routeObject.Query.stops.features.push(new esri.Graphic(ptB, null, { name: $("#TilSted").val() }));

                trafikanten.map.route.solveRoute(trafikanten.map.route.routeObject.Query.stops.features, ptA, ptB);
            });
        });

    },


    solveRoute: function (features, ptA, ptB) {
        if (features.length == 2) {
            trafikanten.map.route.routeObject.Query.stops.features = features;
            if (trafikanten.map.route.routeLayer == null) {
                trafikanten.map.route.routeLayer = new esri.layers.GraphicsLayer();
                trafikanten.map.MapInstance.addLayer(trafikanten.map.route.routeLayer);
            }

            trafikanten.map.route.routeObject.Task.solve(trafikanten.map.route.routeObject.Query, function (routeResults, barriers, message) {
                // Clear map graphics before adding the route
                trafikanten.map.route.routeLayer.clear();

                // Get directions
                var directions = routeResults[0].directions;
                // console.log(directions);
                // console.log(routeResults[0]);
                // Draw route
                trafikanten.map.route.routeLayer.add(new esri.Graphic(routeResults[0].route.geometry, trafikanten.map.route.routeSymbol));

                var iconStart = new esri.symbol.PictureMarkerSymbol("/styles/img/icon_pointer_start_walk.png", 56, 56);
                var iconStop = new esri.symbol.PictureMarkerSymbol("/styles/img/icon_pointer_stop_walk.png", 56, 56);
                if (en) {
                    iconStop = new esri.symbol.PictureMarkerSymbol("/styles/img/icon_pointer_stop_walk_en.png", 56, 56);
                }

                trafikanten.map.route.routeLayer.add(new esri.Graphic(ptA, iconStart));
                trafikanten.map.route.routeLayer.add(new esri.Graphic(ptB, iconStop));

                // Set global direction data (for zoom functions)
                trafikanten.map.route.directions = directions;

                // console.log(directions);

                trafikanten.map.route.directionFeatures = directions.features;

                // Fill in summary
                var en_dist = "Total distance";
                var no_dist = "Total lengde";
                var en_time = "Total time";
                var no_time = "Total tid";
                $("#summary").html((en ? en_dist : no_dist) + ": " + trafikanten.map.route.formatDistance(directions.totalLength, "m") + "<br />" + (en ? en_time : no_time) + ": " + trafikanten.map.route.formatTime(directions.totalTime));

                // Fill in detailed list
                var dirStrings = ["<ol>"];
                for (var i = 0; i < directions.features.length; i++) {
                    var feature = directions.features[i];
                    var txt = feature.attributes.text;
                    if (feature.attributes.length || feature.attributes.time) {
                        txt += " (";
                        if (feature.attributes.length) {
                            txt += trafikanten.map.route.formatDistance(feature.attributes.length, "m");
                        }
                        if (feature.attributes.time) {
                            if (feature.attributes.length) {
                                txt += ", ";
                            }
                            txt += trafikanten.map.route.formatTime(feature.attributes.time);
                        }
                        txt += ")";
                    }
                    // var item = "<li onclick='trafikanten.map.route.zoomToSegment(" + i + "); return false;' class=\"segment\"><a href=\"#\">" + txt + "</a></li>";
                    var item = "<li class=\"segment\">" + txt + "</li>";
                    dirStrings.push(item);
                }
                dirStrings.push("</ol>");

                $("#directions").html(dirStrings.join(""));

                trafikanten.map.route.zoomToFullRoute();

            }, function (error) {
                // $("#directionsError").html("Error:<br>" + error );
                // $("#directionsError").html(en?"Error during loading of walkway":"Feil under lasting av gangtrasé.");
                var en_way = "Can't find a walkway from '" + $("#FraSted").val() + "' to '" + $("#TilSted").val() + "'";
                var no_way = "Finner ingen gangvei fra '" + $("#FraSted").val() + "' til '" + $("#TilSted").val() + "'";

                if ($("#FraSted").val() == $("#TilSted").val()) {
                    en_way = "You can't search for a walkway from and to the same address";
                    no_way = "Du kan ikke s&oslash;ke p&aring; gangvei fra og til samme adresse";
                }
                $("#directionsError").html(en ? en_way : no_way);
            });
        }
    },
    // Zoom so the route fills the map
    zoomToFullRoute: function () {
        trafikanten.map.route.routeLayer.remove(trafikanten.map.route.segmentGraphic);
        trafikanten.map.route.segmentGraphic = null;
        trafikanten.map.MapInstance.setExtent(trafikanten.map.route.directions.extent.expand(1.1), true);
    },
    //Zoom to the appropriate segment when the user clicks a hyperlink in the directions list
    zoomToSegment: function (index) {
        var segment = trafikanten.map.route.directionFeatures[index];
        trafikanten.map.MapInstance.setExtent(segment.geometry.getExtent(), true);
        if (!trafikanten.map.route.segmentGraphic) {
            trafikanten.map.route.segmentGraphic = trafikanten.map.route.routeLayer.add(new esri.Graphic(segment.geometry, new esri.symbol.SimpleLineSymbol().setColor(new dojo.Color([255, 0, 0, 0.5])).setWidth(8)));
        }
        else {
            trafikanten.map.route.segmentGraphic.setGeometry(segment.geometry);
        }
    },
    //Format the time as hours and minutes
    formatTime: function (time) {
        var hr = Math.floor(time / 60), //Important to use math.floor with hours
            min = Math.round(time % 60);

        var en_hr = " h ";
        var no_hr = " t ";

        var en_min = " min";
        var no_min = " min";

        if (hr < 1 && min < 1) {
            // return Math.round((time * 60)) + " sekund(er)";
            var en_less = "less than a minute";
            var no_less = "under ett minutt";
            return en ? en_less : no_less;
        }
        else if (hr < 1) {

            return min + (en ? en_min : no_min);
        }

        return hr + (en ? en_hr : no_hr) + min + (en ? en_min : no_min);
    },

    //Round the distance to the nearest hundredth of a unit
    formatDistance: function (dist, units) {
        // console.log(dist);
        // dist *= 1000;
        var d = Math.round(dist); // * 10) / 10;
        if (d === 0) {
            return ""
        }

        return d + " " + units;
    }
};


trafikanten.map.query =
{
    IdentifyTask: null,
    IdentifyTaskSalepoints: null,
    IdentifyParams: null,
    IdentifyParamsSalepoints: null,
    RetryCount: 0,
    MaxRetry: 10,
    MaxCount: 3,
    Tolerance4Stop: 3,
    Tolerance4ClosestStops: 50,
    Tolerance4Salepoint: 10,
    DeltaExtent: 150,
    RouteStartPoint: null,
    RouteStopPoint: null,

    /*
    doClosestStopsQuery: function(map, evt, count) {
    var identifyParams = trafikanten.map.query.IdentifyParams;
    identifyParams.tolerance = trafikanten.map.query.calculateTolerance(identifyParams.tolerance, count);
    identifyParams.geometry = evt.mapPoint;
    identifyParams.mapExtent = trafikanten.map.query.calculateExtent(evt.mapPoint, identifyParams, count);

    trafikanten.map.query.IdentifyTask.execute(trafikanten.map.query.IdentifyParams, function(results) { trafikanten.map.callback.getClosestStopsComplete(results, evt); });
    },

    calculateTolerance: function(tolerance, count) {
    trafikanten.map.query.RetryCount += 1;
    //console.log(trafikanten.map.query.RetryCount);
    if (count == trafikanten.map.query.MaxCount) {
    return trafikanten.map.query.Tolerance4ClosestStops;
    }
    else if (count == 0) {
    return tolerance + 7;
    }
    else {
    return tolerance - count;
    }
    },

    calculateExtent: function(mapPoint, identifyParams, count) {
    var delta = trafikanten.map.query.DeltaExtent;
    var extent;
    if (count == trafikanten.map.query.MaxCount) {
    extent = new esri.geometry.Extent(mapPoint.x - delta, mapPoint.y - delta, mapPoint.x + delta, mapPoint.y + delta);
    }
    else if (count == 0) {
    extent = identifyParams.mapExtent.expand(1.2);
    }
    else {
    extent = identifyParams.mapExtent.expand(0.8);
    }
    return extent;
    },
    */
    initIdentifyTask: function () {
        // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        // STOPS
        trafikanten.map.query.IdentifyTask = new esri.tasks.IdentifyTask(trafikanten.map.layers.Holdeplasser);
        // trafikanten.map.query.IdentifyTask = new esri.tasks.IdentifyTask(trafikanten.map.layers.Utsalgssteder);

        var identifyParams = new esri.tasks.IdentifyParameters();
        identifyParams.tolerance = trafikanten.map.query.Tolerance4Stop;
        identifyParams.returnGeometry = true;
        identifyParams.layerIds = [0];
        identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_ALL;

        trafikanten.map.query.IdentifyParams = identifyParams;

        // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        // SALEPOINTS 
        trafikanten.map.query.IdentifyTaskSalepoints = new esri.tasks.IdentifyTask(trafikanten.map.layers.Utsalgssteder);

        var identifyParams2 = new esri.tasks.IdentifyParameters();
        identifyParams2.tolerance = trafikanten.map.query.Tolerance4Salepoint;
        identifyParams2.returnGeometry = true;
        identifyParams2.layerIds = [0, 1];
        identifyParams2.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;

        trafikanten.map.query.IdentifyParamsSalepoints = identifyParams2;

        // Add mouse event handlers
        dojo.connect(trafikanten.map.MapInstance, 'onClick', trafikanten.map.events.mapOnClick);
        dojo.connect(trafikanten.map.MapInstance, 'onMouseDown', trafikanten.map.events.mapOnMouseDown);
    },

    doIdentifyTask: function (map, evt, rightClick) {

        var defTaskStops = new dojo.Deferred(), defTaskSalepoints = new dojo.Deferred;
        var dlTasks = new dojo.DeferredList([defTaskStops, defTaskSalepoints]);

        dlTasks.then(function (results) {
            trafikanten.map.callback.identifyComplete(results, evt, rightClick, map);
        });

        trafikanten.map.query.IdentifyParams.geometry = evt.mapPoint;
        trafikanten.map.query.IdentifyParams.mapExtent = map.extent;
        trafikanten.map.query.IdentifyTask.execute(trafikanten.map.query.IdentifyParams, defTaskStops.callback);

        trafikanten.map.query.IdentifyParamsSalepoints.geometry = evt.mapPoint;
        trafikanten.map.query.IdentifyParamsSalepoints.mapExtent = map.extent;
        trafikanten.map.query.IdentifyTaskSalepoints.execute(trafikanten.map.query.IdentifyParamsSalepoints, defTaskSalepoints.callback);

    },


    projectCoordinate: function (point, map, onComplete) {
        var x = point.geometry.x;
        var y = point.geometry.y;
        var geometry = '{ "geometryType":"esriGeometryPoint", "geometries": [ { "x": ' + x + ', "y": ' + y + ', "spatialReference": { "wkid": 32632 } } ] }';

        $.getJSON(trafikanten.map.services.Geometry + "/project?f=json&outSR=32633&inSR=32632&geometries=" + geometry + "&callback=?", function (data) {
            var npoint = data.geometries[0];
            if (typeof onComplete == "function") {
                onComplete(npoint, map);
            } else {
                // console.log(npoint);
                trafikanten.map.focusOnStop(npoint, map);
            }
        });
    },

    /*
    _old_projectCoordinate: function(graphic, map, onComplete){
    var gsvc = new esri.tasks.GeometryService(trafikanten.map.layers.Geometry);
    var outSR = new esri.SpatialReference({ wkid: 32633 });

    if (!map) {
    // Use singleton map
    gsvc.project([graphic], outSR, trafikanten.map.callback.onProjectCompleted, trafikanten.map.callback.errorHandlerTrafikanten);
    } else {
    gsvc.project([graphic], outSR, function(features) {
    if (features && features.length > 0) {
    var point = features[0].geometry;

    if(typeof onComplete == "function")
    {
    onComplete(point, map);
    }else{
									
    var symbol = new esri.symbol.PictureMarkerSymbol("/styles/img/icon_pointer_here.png",64, 64);

    if (map.graphics) {
    map.graphics.add(new esri.Graphic(point, symbol));
    }
									
    trafikanten.map.focusOnStop(point, map);
    }
    }
    else {
    $('#mapResult').html('Husnummeret ble ikke funnet.');
    }

    }, trafikanten.map.callback.errorHandlerTrafikanten);
    }

    },
    */
    loadErrorHandler: function (taskToHandle) {
        dojo.connect(taskToHandle, 'onError', trafikanten.map.callback.errorHandler);
    }
};

trafikanten.map.queryObject =
{
    Task: '',
    Query: ''
};

trafikanten.map.stop =
{
    ///     <summary>
    ///           1: Hjelpe klasse for å generer innhold i popup boks for stoppested
    ///     </summary>
    sanntidBaseUrl: '/no/Sanntid/For',
    avgangerBaseUrl: '/no/Stoppested',
    ankomsterBaseUrl: '/no/Stoppested',

    getUrlFromBase: function (parsedStop, baseUrl) {
        if (parsedStop && baseUrl) {
            return baseUrl + '/' + trafikanten.map.stop.URLencode(parsedStop);
        }
    },



    getLines: function (hplId, navn, callback) {
        var linesURL = trafikanten.map.services.GetLines + hplId + "/?jsoncallback=?";
        var validateURL = trafikanten.map.services.IsValidPlace + escape(navn) + "/?jsoncallback=?";
        var showRealtime = false;

        //console.log(validateURL);
        $.getJSON(validateURL,
				function (data) {
				    if (data == true) {
				        if (trafikanten.map.settings.RealtimeEnabled) {
				            showRealtime = true;
				        }
				    }

				    if (trafikanten.map.settings.LinesEnabled) {
				        $.getJSON(linesURL,
							function (data) {
							    var lines = "<li class=\"clearfix\">";
							    var lstart = lines;
							    var count = data.length > trafikanten.map.settings.LinesMax ? trafikanten.map.settings.LinesMax : data.length;
							    for (var i = 0; i < count; i++) {
							        var lID = data[i]['LineID'];
							        var lName = data[i]['LineName'];
							        var lTrans = data[i]['Transportation'];
							        lines += "<div class=\"blueSquare\">" + lName + "</div>";
							    }
							    if (lines == lstart) {
							        lines = "";
							    } else {
							        if (count < data.length) {
							            var first = true;
							            var title = "";
							            for (var i = count; i < data.length; i++) {
							                var lID = data[i]['LineID'];
							                var lName = data[i]['LineName'];
							                var lTrans = data[i]['Transportation'];
							                if (!first) {
							                    title += ", ";
							                } else {
							                    first = false;
							                }
							                title += $.trim(lName);
							            }

							            lines += "<dfn class=\"dotdotdot\" title=\"" + title + "\">...</dfn>";
							        }
							        lines += "</li>";
							    }

							    callback(lines, showRealtime);

							});
				    } else {
				        callback("", showRealtime);
				    }
				});
    },

    sanntidLink: function (hplId, navn) {
        var en_realtime = "Show realtime information";
        var no_realtime = "Vis sanntidsinformasjon";
        var realtime = en ? en_realtime : no_realtime;

        var parsedFrom = '(' + hplId + ')' + navn;
        var sanntidUrl = trafikanten.map.stop.getUrlFromBase(parsedFrom, trafikanten.map.stop.sanntidBaseUrl);

        //        return '<a href="' + sanntidUrl + '" class="sanntidLink" onclick="trafikanten.map.events.handleContextMenuClick(this);return false;" >Vis sanntidsinformasjon</a>';
        return '<a href="' + sanntidUrl + '" class="sanntidLink">' + realtime + '</a>';
    },

    avgangerLink: function (hplId, navn, showRealtime) {
        var en_rt = showRealtime ? " / real time" : "";
        var no_rt = showRealtime ? " / sanntid" : "";
        var en_showdep = "Show departures" + en_rt + " from...";
        var no_showdep = "Vis avganger" + no_rt + " fra...";
        var showdep = en ? en_showdep : no_showdep;

        var parsedFrom = '(' + hplId + ')' + navn;
        var departureUrl = trafikanten.map.stop.avgangerBaseUrl + '/' + trafikanten.map.stop.URLencode(parsedFrom) + '/Avganger';
        return '<a href="' + departureUrl + '" class="departureLink">' + showdep + '</a>';
    },

    ankomsterLink: function (hplId, navn, showRealtime) {
        var en_rt = showRealtime ? "real time/" : "";
        //console.log(showRealtime+ " - " + en_rt);
        var no_rt = showRealtime ? "sanntid/" : "";
        var en_showarr = "Show " + en_rt + "arrivals here";
        var no_showarr = "Vis " + no_rt + "ankomster hit";
        var showarr = en ? en_showarr : no_showarr;

        var parsedFrom = "(" + hplId + ")" + navn;
        var arrivalUrl = trafikanten.map.stop.ankomsterBaseUrl + '/' + trafikanten.map.stop.URLencode(parsedFrom) + '/Ankomster';
        return '<a href="' + arrivalUrl + '" class="arrivalLink">' + showarr + '</a>';
    },

    buildMenuForSalepoint: function (results, evt, map) {
        // SALEPOINTS
        var result = results[0];
        var graphic = result.feature;
        var point = graphic.geometry;
        var navn = graphic.attributes['Name'];

        var adr = graphic.attributes['Address'];
        var zip = graphic.attributes['ZipCode'];
        var city = graphic.attributes['ZipCity'];
        var chain = graphic.attributes['Chain'];

        var content = "<ul class='infoWindowList'>";

        content += "<li>" + adr + "</li>";
        content += "<li>" + zip + " " + city + "</li>";
        content += "<li>" + chain + "</li>";

        content += "</ul>"

        trafikanten.map.mapShowMenu(map, navn, content, evt, point);
    },

    buildMenuForStop: function (results, evt, map) {
        // STOPS
        // results = results[0][1];
        var result = results[0];
        var graphic = result.feature;
        var point = graphic.geometry;

        var hplId = graphic.attributes['Nummer'];
        var navn = graphic.attributes['Navn'];
        var type = graphic.attributes['Type_'];


        var no_dep = "Reis fra...";
        var en_dep = "Travel from...";
        var dep = en ? en_dep : no_dep;

        var no_arr = "Reis til...";
        var en_arr = "Travel to...";
        var arr = en ? en_arr : no_arr;

        var setDeparture = "<a href='#' onclick='trafikanten.map.stop.setDeparture(\"" + (navn) + "\",\"" + hplId + "\"); return false;'>" + dep + "</a>";
        var setArrival = "<a href='#' onclick='trafikanten.map.stop.setArrival(\"" + (navn) + "\",\"" + hplId + "\"); return false;'>" + arr + "</a>";
        var showRealtime = false;

        var contentA = "<ul class='infoWindowList'>";


        var contentB = "";
        if (trafikanten.map.settings.ShortcutsEnabled) {
            contentB += "<li>${Departure}</li>";
            contentB += "<li>${Arrival}</li>";
        }
        if (trafikanten.map.settings.RealtimeEnabled) {
            contentB += "<li>${ShowDepartures}</li>";
        }

        contentB += "</ul>"



        if (!trafikanten.map.settings.ShortcutsEnabled) {
            setDeparture = "";
            setArrival = "";
        }

        if (trafikanten.map.settings.LinesEnabled) {
            // get lines
            trafikanten.map.stop.getLines(hplId, navn, function (lines, showRealtime) {
                var showDepartures = trafikanten.map.stop.avgangerLink(hplId, navn, showRealtime);
                contentA += "<li>" + lines + "</li>";
                trafikanten.map.mapShowMenu(map, navn, contentA + contentB, evt, point);
            });
        } else {
            // no lines
            trafikanten.map.mapShowMenu(map, navn, contentA + contentB, evt, point);
        }
    },

    buildMenu: function (hplId, navn, map, evt, point) {

        trafikanten.map.mapShowMenu(map, navn, "", evt, point);
    },


    setDeparture: function (name, hpId) {
        trafikanten.travelquery.set_departure_with_id(name, hpId);
    },

    setArrival: function (name, hpId) {
        trafikanten.travelquery.set_arrival_with_id(name, hpId);
    },

    showArrivals: function (hplId) {
        //console.log('showArrivals: ' + hplId);
    },

    URLencode: function (sStr) {
        return sStr.replace(/!/g, '%21').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+').replace(/\./g, '').replace(/\s/g, '%20');
    },

    NameEncode: function (sStr) {
        return sStr.replace(/!/g, '%21').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+').replace(/\./g, '');
    },

    getDateTimeNow: function () {
        var now = new Date();

        var d = now.getDate()
        var day = (d < 10) ? '0' + d : d;

        return day + (now.getMonth() + 1).toString() + now.getFullYear() + now.getHours() + now.getMinutes();
    }
};

trafikanten.travelquery =
{
    set_departure: function (v) {
        v = $.trim(v.replace('#', '').replace('/', ''));
        $('#' + trafikanten.map.settings.input.From).val(v);
    },
    set_arrival: function (v) {
        v = $.trim(v.replace('#', '').replace('/', ''));
        $('#' + trafikanten.map.settings.input.To).val(v);
    },
    set_departure_with_id: function (v, id) {
        v = $.trim(v.replace('#', '').replace('/', ''));
        $('#Forrige' + trafikanten.map.settings.input.From).val(v);
        $('#' + trafikanten.map.settings.input.From).val(v);
        $('#' + trafikanten.map.settings.input.From + 'Id').val(id);
    },
    set_arrival_with_id: function (v, id) {

        v = $.trim(v.replace('#', '').replace('/', ''));
        $('#Forrige' + trafikanten.map.settings.input.To).val(v);
        $('#' + trafikanten.map.settings.input.To).val(v);
        $('#' + trafikanten.map.settings.input.To + 'Id').val(id);
    },

    // Valid chars test
    //Input as many invalid characters you wish to deny in ^[^<>`~!/@\#}$%:;_^{&*=|'+]+$
    stoppested: function (value, element) {
        return this.optional(element) || /^[^<>`~!\/@#\?}$%:;_^{&*=|+]+$/.test(value);
    }
};

trafikanten.fullRoute =
{
    // Full travel route counter
    routeCount: 0,
    routeMax: 0,

    // Route start and stop points
    // Stop ids
    startStop: null,
    endStop: null,
    // Coordinates
    startPos: null,
    endPos: null,


    plotStops: function (stopsLayer, route, startId, stopId, type, map, mp) {
        //console.log("Plotting stops");
        var icon, gsvc;

        gsvc = trafikanten.map.gsvc;



        switch (type) {
            case 0: // Gange
            case 1: // Flybuss
            case 2: // Buss
                icon = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Buss.path, trafikanten.map.settings.icons.Buss.width, trafikanten.map.settings.icons.Buss.height);
                break;
            case 5: // Båt
                icon = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Baat.path, trafikanten.map.settings.icons.Baat.width, trafikanten.map.settings.icons.Baat.height);
                break;
            case 4: // Flytog
            case 6: // Tog
                icon = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Tog.path, trafikanten.map.settings.icons.Tog.width, trafikanten.map.settings.icons.Tog.height);
                break;
            case 7: // Trikk
                icon = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Trikk.path, trafikanten.map.settings.icons.Trikk.width, trafikanten.map.settings.icons.Trikk.height);
                break;
            case 8: // T-bane
                icon = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Tbane.path, trafikanten.map.settings.icons.Tbane.width, trafikanten.map.settings.icons.Tbane.height);
                break;
            default:
                //console.log(type);
                break;
        }

        // Start fetching the route
        $.getJSON(trafikanten.map.services.Trip + route + "/?time=" + trafikanten.map.stop.getDateTimeNow() + "&jsoncallback=?",
				function (data) {
				    //console.log("=== "+ route + " ===");

				    var outSR, hasStarted, hasStopped;

				    outSR = trafikanten.map.outSR;
				    hasStarted = false;
				    hasStopped = false;

				    var itemCount = 0;
				    var itemMax = 0;

				    var startI = 0, endI = 0;
				    var skip = new Array(data['Stops'].length);

				    // Count items
				    for (var i = 0; i < data['Stops'].length; i++) {
				        skip[i] = 0;
				        var item = data['Stops'][i];

				        if (hasStopped) {
				            break;
				        }

				        //console.log(startId + " - " + item.ID);
				        if ((!hasStarted && startId && item.ID === startId) || !startId) {
				            //console.log("found start");
				            startI = i;
				            hasStarted = true;
				        }

				        if (!hasStarted) {
				            continue;
				        }

				        //console.log("xx"+item.X+","+item.Y);
				        if ((item.X == 0 || item.Y == 0) && hasStarted) {
				            //console.log("skip " + i);
				            skip[i] = 1;
				            continue;
				            //return;
				        }

				        // Project 
				        var point = new esri.geometry.Point(item.X, item.Y, new esri.SpatialReference({ wkid: 32632 }));

				        if (trafikanten.fullRoute.startStop == item.ID) {
				            trafikanten.fullRoute.startStop = null;
				            trafikanten.fullRoute.startPos = point;
				        } else if (trafikanten.fullRoute.endStop == item.ID) {
				            trafikanten.fullRoute.endStop = null;
				            trafikanten.fullRoute.endPos = point;
				        }

				        itemMax++;

				        if (stopId && item.ID === stopId) {
				            //console.log("found end");

				            hasStopped = true;
				            endI = i + 1;
				            break;
				        }
				    }

				    if (endI == 0) {
				        endI = data['Stops'].length;
				    }

				    hasStarted = false;
				    hasStopped = false;

				    for (var i = startI; i < endI; i++) {
				        if (skip[i] == 1) { continue; }
				        var item = data['Stops'][i];
				        // Project 
				        //console.log(isNaN(item.X)+","+isNaN(item.Y)+"  ---- _-- ");
				        var point = new esri.geometry.Point(item.X, item.Y, new esri.SpatialReference({ wkid: 32632 }));
				        // console.log(item);
				        var at = item.ArrivalTime;
				        var dt = item.DepartureTime;
				        // console.log(at+","+dt);
				        at = new Date(parseInt(at.substr(6)));
				        dt = new Date(parseInt(dt.substr(6)));

				        var graphic = new esri.Graphic(point, icon);
				        var no_baard = (item.BoardingAllowed && !item.AlightingAllowed ? "Kun p&aring;stigning" : "");
				        var en_baard = (item.BoardingAllowed && !item.AlightingAllowed ? "Boarding only" : "");
				        no_baard = (!item.BoardingAllowed && item.AlightingAllowed ? "Kun avstigning" : no_baard);
				        en_baard = (!item.BoardingAllowed && item.AlightingAllowed ? "Alighting only" : en_baard);
				        var baard = en ? en_baard : no_baard;
				        graphic.setAttributes({ "NAME": item.Name, "ATIME": at.toLocaleTimeString().substring(0, 5), "DTIME": dt.toLocaleTimeString().substring(0, 5), "BALLOWED": baard });
				        gsvc.project([graphic], outSR, function (features) {
				            var g = features[0];
				            if (mp != null) {
				                mp.addPoint(g.geometry);
				                //console.log(g.geometry.x+","+g.geometry.y);
				            }
				            var en_data = "${NAME}<br />Arrival: ${ATIME}<br />Departure: ${DTIME}<br />${BALLOWED} ";
				            var no_data = "${NAME}<br />Ankomst: ${ATIME}<br />Avgang: ${DTIME}<br />${BALLOWED} ";

				            g.setInfoTemplate(new esri.InfoTemplate("Tid", en ? en_data : no_data));

				            stopsLayer.add(g);

				            itemCount++;
				            //console.log("items: "+itemCount+"/"+itemMax);
				            if (itemCount >= itemMax) {
				                trafikanten.fullRoute.routeCount++;

				                //console.log("stops: "+trafikanten.map.routeCount + " - " + trafikanten.map.routeMax);

				                if (trafikanten.fullRoute.routeCount >= trafikanten.fullRoute.routeMax) {
				                    trafikanten.fullRoute.finishRoute(map, mp);
				                }
				            }
				        });
				    }
				}
			  );
    },
    plotWalkPath: function (stopsLayer, ptA, ptB, after, map, mp, onlyThis) {
        var queryObject = {};
        queryObject.Task = new esri.tasks.RouteTask(trafikanten.map.services.Route);
        queryObject.Query = new esri.tasks.RouteParameters();

        queryObject.Query.impedanceAttribute = "Minutes";
        queryObject.Query.restrictionAttributes = [];
        queryObject.Query.useHierarchy = false;
        queryObject.Query.ignoreInvalidLocations = true;
        queryObject.Query.restrictUTurns = "esriNFSBAllowBacktrack";
        queryObject.Query.outSpatialReference = new esri.SpatialReference({ wkid: 32633 });
        queryObject.Query.findBestSequence = false;
        queryObject.Query.useTimeWindows = false;
        queryObject.Query.preserveFirstStop = true;
        queryObject.Query.preserveLastStop = true;
        queryObject.Query.outputLines = "esriNAOutputLineTrueShapeWithMeasure";

        queryObject.Query.directionsLanguage = en ? "en-US" : "no-NO";
        // queryObject.Query.directionsLanguage = "en_US";
        queryObject.Query.directionsLengthUnits = "esriNAUMeters";
        queryObject.Query.directionsTimeAttribute = "Minutes";

        queryObject.Query.returnBarriers = false;
        queryObject.Query.returnDirections = true;
        queryObject.Query.returnRoutes = true;
        queryObject.Query.returnStops = false;

        queryObject.Query.stops = new esri.tasks.FeatureSet(); //{"features":[{"geometry":{"x":260489.68580137176,"y":6649917.191965352},"attributes":{"address":"Stopp # 0"}},{"geometry":{"x":262085.12649225313,"y":6650663.318457604},"attributes":{"address":"Stopp # 1"}}]});

        queryObject.Query.stops.features.push(new esri.Graphic(ptA, null));
        queryObject.Query.stops.features.push(new esri.Graphic(ptB, null));

        var routeSymbol = new esri.symbol.SimpleLineSymbol().setColor(new dojo.Color([0, 0, 255, 0.5])).setWidth(5);
        queryObject.Task.solve(queryObject.Query, function (routeResults, barriers, message) {
            // Draw route
            var g = new esri.Graphic(routeResults[0].route.geometry, routeSymbol);
            g.setAttributes({ "TIME": Math.round(routeResults[0].directions.totalTime), "LENGTH": trafikanten.map.route.formatDistance(routeResults[0].directions.totalLength, "m") });

            var no_gtime = "Gangavstand: ${LENGTH}<br />Gangtid: ${TIME} min";
            var en_gtime = "Walking distance: ${LENGTH} m<br />Walking time: ${TIME} min";
            var gtime = en ? en_gtime : no_gtime;

            g.setInfoTemplate(new esri.InfoTemplate("Gangtid", gtime));

            stopsLayer.add(g);

            trafikanten.fullRoute.routeCount++;
            //console.log("path: "+trafikanten.fullRoute.routeCount + " - " + trafikanten.fullRoute.routeMax);

            if (trafikanten.fullRoute.routeCount >= trafikanten.fullRoute.routeMax) {
                trafikanten.fullRoute.finishRoute(map, mp);
            } else if (onlyThis) {
                // Project the start and end point
                var gsvc = trafikanten.map.gsvc;
                var outSR = trafikanten.map.outSR;

                // var iconStart = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 20, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([0, 204, 51, 1]), 3), new dojo.Color([0, 0, 0, 0]));
                // var iconStop = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 20, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([230, 0, 0, 1]), 3), new dojo.Color([0, 0, 0, 0]));
                var iconStart = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.WalkStart.path, trafikanten.map.settings.icons.WalkStart.width, trafikanten.map.settings.icons.WalkStart.height);
                var iconStop = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.WalkStopp.path, trafikanten.map.settings.icons.WalkStopp.width, trafikanten.map.settings.icons.WalkStopp.height);
                if (en) {
                    iconStop = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.WalkStop.path, trafikanten.map.settings.icons.WalkStop.width, trafikanten.map.settings.icons.WalkStop.height);
                }

                stopsLayer.add(new esri.Graphic(ptA, iconStart));
                stopsLayer.add(new esri.Graphic(ptB, iconStop));
                /*
                gsvc.project([new esri.Graphic(ptA, iconStart)], outSR, function(features) {
                var gA = features[0];
                trafikanten.map.MapInstance.graphics.add(gA);
                gsvc.project([new esri.Graphic(ptB, iconStop)], outSR, function(features) {
                var gB = features[0];
                trafikanten.map.MapInstance.graphics.add(gB);
                });
                });					
                */
            }

            // Run custom on complete function
            if (after != null) { // typeof == function
                after(routeResults[0].directions.extent.expand(1.2));
            }

        }, function (error) {
            // console.log("== ERROR Drawing path ==");
            // console.log(error);
        });
    },

    plotPath: function (stopsLayer, from, to, after, map, mp, onlyThis) {
        //console.log("Plotting path");
        var gsvc = trafikanten.map.gsvc;
        var outSR = trafikanten.map.outSR;
        gsvc.project([new esri.Graphic(from, null)], outSR, function (features) {
            var ptA = features[0].geometry;
            //console.log(ptA.x+","+ptA.y);
            if (mp != null) {
                //console.log(ptA.x+","+ptA.y);
                mp.addPoint(ptA);
            }
            gsvc.project([new esri.Graphic(to, null)], outSR, function (features) {
                var ptB = features[0].geometry;
                //console.log(ptB.x+","+ptB.y);
                if (mp != null) {
                    mp.addPoint(ptB);
                }
                trafikanten.fullRoute.plotWalkPath(stopsLayer, ptA, ptB, after, map, mp, onlyThis);
            });
        });

    },

    plotRoute: function (map, data) //start, stop)
    {
        if (!map) {
            //alert("no map to plot on");
            return;
        }
        //console.log("plotting route");
        trafikanten.fullRoute.routeCount = 0;

        //console.log(data.length);
        if (data[data.length - 1] == undefined) {
            data.splice(data.length - 1, 1);
        }
        //console.log(data);

        trafikanten.fullRoute.routeMax = data.length;

        $("#" + map.id).parent().addClass("loading");

        //console.log("Route: "+trafikanten.fullRoute.routeCount + " - " + trafikanten.fullRoute.routeMax);


        // Extent helper
        var multiPoint = new esri.geometry.Multipoint(new esri.SpatialReference({ wkid: 32633 }));
        // Stops layer
        var stopsLayer = new esri.layers.GraphicsLayer();


        // Mouse over effect on stops
        $('<div class="mouseOverMapHelperTravelRoute"></div>').appendTo($("#" + map.id));
        dojo.connect(stopsLayer, "onMouseMove", function (evt) {
            var g = evt.graphic;
            // $(".mouseOverMapHelperTravelRoute").remove();
            map.reposition();
            $(".mouseOverMapHelperTravelRoute").html(g.getContent());
            $(".mouseOverMapHelperTravelRoute").css({ "left": evt.screenPoint.x + 10, "top": evt.screenPoint.y - 10 }).show();
        });
        dojo.connect(stopsLayer, "onMouseOut", function () { $(".mouseOverMapHelperTravelRoute").hide(); });

        // Add the layer, and reorder it
        map.addLayer(stopsLayer);
        map.reorderLayer(stopsLayer, 1);

        // Loop through the data-set		
        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item == undefined) {
                trafikanten.fullRoute.routeMax--;
                break;
            }

            //console.log(i + " - " + item[0]);
            if (item[0] != 0) {
                if (i == 0) {
                    trafikanten.fullRoute.startStop = item[1];
                }
                if (i == trafikanten.fullRoute.routeMax - 1) {
                    trafikanten.fullRoute.endStop = item[2];
                }
                trafikanten.fullRoute.plotStops(stopsLayer, item[0], item[1], item[2], item[3], map, multiPoint);
            } else {
                var inSR = new esri.SpatialReference({ wkid: 32632 });
                if (item[1][0] == 0 || item[1][1] == 0 || item[2][0] == 0 || item[2][1] == 0) {
                    //console.log("Feil ved lasting av kart. Gangtrase mangler koordinat");
                    //alert("Feil ved lasting av kart. Gangtrase mangler koordinat");
                    trafikanten.fullRoute.routeCount++;
                    //console.log("x - "+trafikanten.fullRoute.routeCount + " - " + trafikanten.fullRoute.routeMax);
                    if (trafikanten.fullRoute.routeCount >= trafikanten.fullRoute.routeMax) {
                        trafikanten.fullRoute.finishRoute(map, mp);
                    }
                    continue;
                }
                var pointA = new esri.geometry.Point(item[1][0], item[1][1], inSR);
                var pointB = new esri.geometry.Point(item[2][0], item[2][1], inSR);

                // Set start position - green box
                if (i == 0) {
                    trafikanten.fullRoute.startPos = pointA;
                }
                // Set end position - red box
                if (i == trafikanten.fullRoute.routeMax - 1) {
                    trafikanten.fullRoute.endPos = pointB;
                }
                trafikanten.fullRoute.plotPath(stopsLayer, pointA, pointB, null, map, multiPoint);
            }
        }

    },
    finishRoute: function (map, mp) {

        $("#" + map.id).parent().removeClass("loading");
        map.setExtent(mp.getExtent(), true);

        var startstopLayer = new esri.layers.GraphicsLayer();
        map.addLayer(startstopLayer);
        map.reorderLayer(startstopLayer, 0);

        // Project the start and end point
        var gsvc = trafikanten.map.gsvc;
        var outSR = trafikanten.map.outSR;

        // var iconStart = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 20, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([0, 204, 51, 1]), 3), new dojo.Color([0, 0, 0, 0]));
        // var iconStop = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 20, new esri.symbol.SimpleLineSymbol('solid', new dojo.Color([230, 0, 0, 1]), 3), new dojo.Color([0, 0, 0, 0]));

        var iconStart = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Start.path, trafikanten.map.settings.icons.Start.width, trafikanten.map.settings.icons.Start.height);
        var iconStop = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Stopp.path, trafikanten.map.settings.icons.Stopp.width, trafikanten.map.settings.icons.Stopp.height);
        if (en) {
            iconStop = new esri.symbol.PictureMarkerSymbol(trafikanten.map.settings.icons.Stop.path, trafikanten.map.settings.icons.Stop.width, trafikanten.map.settings.icons.Stop.height);
        }

        gsvc.project([new esri.Graphic(trafikanten.fullRoute.startPos, iconStart)], outSR, function (features) {
            var gA = features[0];
            startstopLayer.add(gA);
            gsvc.project([new esri.Graphic(trafikanten.fullRoute.endPos, iconStop)], outSR, function (features) {
                var gB = features[0];
                startstopLayer.add(gB);
            });
        });
    }
};
