﻿/*!
 * Namespace for the maps scripts
 */
var swebusMaps = function() {
    var maps = [],
    routeLabel = null,    
    BLUE_ICON = null,
    RED_ICON = null,
    markerIcon = null,
    
    // Initializes the maps namespace
    init = function() {
        if (typeof google != "undefined") {
            jQuery(window).unload(google.maps.Unload);
            BLUE_ICON = loadIcon("blue");
            RED_ICON = loadIcon("red");
        }
        
        jQuery("body").mousemove(function(e) {
            var offset = routeLabel.height() / 2;
            routeLabel.css({ "top": e.pageY - offset + "px", "left": e.pageX + 5 + "px" });
        });
        
        routeLabel = jQuery("<div>", { "id": "route-label", "class": "linjelabel_1" }).css({ "display": "none" });
        jQuery("<div>", { "class": "top" }).html("&nbsp;").appendTo(routeLabel);
        var middle = jQuery("<div>", { "class": "middle" }).appendTo(routeLabel);
        jQuery("<div>", { "class": "arrow" }).appendTo(middle);
        jQuery("<div>", { "class": "bottom" }).html("&nbsp;").appendTo(routeLabel);
        routeLabel.appendTo("body");
        
        jQuery.ajaxSetup({
            url: "/maps/api/ajax/ajaxservice.aspx",
            dataType: "json"
        });
    },
    
    // Loads marker icon depending on color
    loadIcon = function(color) {
        var icon = new google.maps.Icon();
        icon.iconSize = new google.maps.Size(20,23);
        icon.iconAnchor = new google.maps.Point(9, 21);
        icon.image = "/Maps/Images/" + color + "_icon.png";
        icon.infoWindowAnchor = new google.maps.Point(9, 2);
        return icon;
    },
    
    // Map Object
    map = function(elementId, mapId) {
        var data = {},
            routes = [],
            pois = [],
            labels = [],
            mapContainer = null,
            mapObject = null,
            mapSelector = null,
            mapElement = null,
            markerManager = null,
            currentTabCategory = null,
            currentCategory = null,
            markerInfoWindow = null,
            
        // Initalizes this map instance
        initializeMap = function(elementId, mapId) {
            mapSelector = "#" + elementId;
            mapElement = jQuery(mapSelector);
            mapContainer = mapElement.parent();
            mapObject = new google.maps.Map2(mapElement[0]);
            mapObject.addControl(new google.maps.LargeMapControl3D());
            // Hide the info window on click
            google.maps.Event.addListener(mapObject, "click", function(event) {
                if (!event && markerInfoWindow.is(":visible")) {
                    markerInfoWindow.hide();
                }
            });
            // Hide the info window on move
            google.maps.Event.addListener(mapObject, "movestart", function(event) {
                if (!event && markerInfoWindow.is(":visible")) {
                    markerInfoWindow.hide();
                }
            });
            
            markerInfoWindow = jQuery("<div>", { "class": "info-window" }).css({ "display": "none", "width": mapObject.getSize().width / 2 + "px" });
            var markerInfoWindowContent = jQuery("<div>", { "class": "content"});
            jQuery("<div>", { "class": "close" }).html("Stäng").appendTo(markerInfoWindowContent)
                .click(function() {
                    markerInfoWindow.hide();
                });
            jQuery("<h2>", { "class": "title"}).appendTo(markerInfoWindowContent);
            jQuery("<div>", { "class": "text"}).appendTo(markerInfoWindowContent);
            markerInfoWindowContent.appendTo(markerInfoWindow);
            markerInfoWindow.appendTo(mapElement);            
            
            bindEventListeners(mapSelector);            

            jQuery.ajax({
                type: "GET",
                data: {
                    type: "GetMap",
                    mapId: mapId
                },
                success: mapDataRecieved
            });  
        },
        
        // Binds all the eventlisteners for this map. Uses the maps selector
        // to be able to attach to events
        bindEventListeners = function(mapSelector) {
            jQuery(document).delegate(mapSelector, "markerClicked", function(event, eventArguments) {
                markerClicked(eventArguments.marker, eventArguments.data);
            });
            
            jQuery(document).delegate(mapSelector, "markerMouseOver", function(event, eventArguments) {
                markerMouseOver(eventArguments.marker, eventArguments.data);
            });
            
            jQuery(document).delegate(mapSelector, "markerMouseOut", function(event, eventArguments) {
                markerMouseOut(eventArguments.marker, eventArguments.data);
            });
        },
        
        // Callback for when json-data was recieved for this map
        mapDataRecieved = function(mapData) {
            data = mapData;
            mapObject.setCenter(new google.maps.LatLng(data.StartLatitude, data.StartLongitude));
            mapObject.setZoom(data.StartZoom);
            if (data.Categories.length > 0) {
                renderCategories();
            } else {
                renderRoutes();
                renderPointsOfInterest();
            }
            
            // Trigger finished loading event
            mapElement.trigger("mapFinishedLoading", { map: mapObject, data: data });
        },
        
        // Renders all the categories (if any) and selects the first
        renderCategories = function() {
            var ul = mapContainer.find("ul.mapCategories");
            if (ul.length == 0) {
                ul = jQuery("<ul>", { "class": "mapCategories" });
            }
            mapContainer.prepend(ul);            
            jQuery.each(data.Categories, function(i, category) {
               addCategoryTab(category, (i == 0)); 
            });
            ul.trigger("categoriesFinishedLoading");
        },
        
        // Adds a category to the map-view
        addCategoryTab = function(category, selected) {
            var ul = mapContainer.children("ul");
            var li = jQuery("<li>", {
                id: "c" + category.Id
            });
            li.appendTo(ul);
            
            var span = jQuery("<span>");
            span.text(category.Name);
            span.click(function() {
                markerInfoWindow.hide();
                jQuery(this).parent().siblings().removeClass("selected");
                jQuery(this).parent().addClass("selected");
                currentTabCategory = category;
                if (category.Categories.length > 0) {
                    li.find("input").removeAttr("checked");
                    li.find("input:first").attr("checked", "checked");
                    li.find("li").removeClass("selected");
                    li.find("li:first").addClass("selected");
                    currentCategory = category.Categories[0];
                } else {
                    currentCategory = category;                                        
                }
                mapObject.clearOverlays();
                renderRoutes();
                renderPointsOfInterest();
            });
            span.appendTo(li);
            
            if (selected) {
                ul.find("li").removeClass("selected");
                li.addClass("selected");
                currentTabCategory = category;
                if (category.Categories.length == 0) {
                    currentCategory = category;
                    mapObject.clearOverlays();
                    renderRoutes();
                    renderPointsOfInterest();
                }
            }
            
            if (category.Categories.length > 0) {
                jQuery.each(category.Categories, function(i, subCategory) {
                    addSubCategory(subCategory, category, (i == 0));
                });
            }
        },
        
        // Adds a subcategory to render
        addSubCategory = function(subCategory, parentCategory, selected) {
            var parent = jQuery("li#c" + parentCategory.Id);
            var ul = parent.find("ul");
            if (ul.length == 0) {
                ul = jQuery("<ul>").appendTo(parent);
            }
            var li = jQuery("<li>", { id: "sc" + subCategory.Id });
            var radio = jQuery("<input />", {
                id: "rb" + subCategory.Id,
                type: "radio",
                name: "subcategories" + parentCategory.Id
            }).click(function() {
                markerInfoWindow.hide();
                li.siblings().removeClass("selected");
                li.addClass("selected");
                currentCategory = subCategory;
                mapObject.clearOverlays();
                renderRoutes();
                renderPointsOfInterest();
            });
            var label = jQuery("<label>", {
                "for": "rb" + subCategory.Id
            }).text(subCategory.Name);
            
            radio.appendTo(li);
            label.appendTo(li);
            li.appendTo(ul);
            
            if (selected) {
                li.siblings().removeClass("selected");
                li.addClass("selected");
                radio.attr("checked", "checked");
                if (currentTabCategory == parentCategory) {
                    currentCategory = subCategory;
                    mapObject.clearOverlays();
                    renderRoutes();
                    renderPointsOfInterest();
                }
            }
            
            ul.trigger("categoriesFinishedLoading");
        },
        
        // Renders all the routes in the active view
        renderRoutes = function() {
            routes.length = 0;      
            jQuery.each(data.Routes, function(i, route) {
                if (currentCategory == null || route.CategoryId == currentCategory.Id) {
                    addRoute(route);
                }
            });
        },
        
        // Adds a route to the map
        addRoute = function(route) {
            var latlngs = [];
            jQuery.each(route.Points, function(i, point) {
                latlngs.push(new google.maps.LatLng(point.Lat, point.Lng));
            });
           var polyline = new google.maps.Polyline(latlngs, route.Color, route.Weight, route.Opacity);
            google.maps.Event.addListener(polyline, "click", function() {
                mapElement.trigger("routeClicked", { route: polyline, data: route });
            });
            // add empty listener to make the cursor a pointer
            google.maps.Event.addListener(polyline, "mouseover", function() {
                polyline.setStrokeStyle({ weight: route.Weight + 3 });                
                if (route.Label != "") {
                    routeLabel.addClass("active");
                    routeLabel.find(".arrow").css({ "color": route.Color }).html(route.Label);
                    routeLabel.show();
                }
            });
            google.maps.Event.addListener(polyline, "mouseout", function() {
                polyline.setStrokeStyle({ weight: route.Weight });
                routeLabel.removeClass("active");
                routeLabel.delay(100).hide();
            });
            polyline.Id = route.Id;
            routes.push(polyline);
            mapObject.addOverlay(polyline);
        },
        
        // Renders all the point of interests
        renderPointsOfInterest = function() {
            pois.length = 0;
            markerManager = new MarkerManager(mapObject, { borderPadding: 0 });
            jQuery.each(data.PointsOfInterest, function(i, poi) {
                if (currentCategory == null || poi.CategoryId == currentCategory.Id) {
                    addPointOfInterest(poi);
                }
            });
//            if (data.Id == 1 && currentCategory != null && currentCategory.Id == 2) {
//                renderLabels();
//            }
        },
        
        // Adds a point to the map
        addPointOfInterest = function(poi) {
            var marker = new google.maps.Marker(new google.maps.LatLng(poi.Latitude, poi.Longitude), { icon: RED_ICON, draggable: true });
            var tooltip = jQuery("<div>", { "id": "tooltip" }).html(poi.Name).css({ "position": "absolute" });
            marker.id = poi.Id;
            marker.tooltip = tooltip;
            marker.disableDragging();
            
            google.maps.Event.addListener(marker, "click", function() {
                mapElement.trigger("markerClicked", { marker: marker, data: poi });
            });
            
            google.maps.Event.addListener(marker, "mouseover", function() {
                mapElement.trigger("markerMouseOver", { marker: marker, data: poi });
            });
            
            google.maps.Event.addListener(marker, "mouseout", function() {
                mapElement.trigger("markerMouseOut", { marker: marker, data: poi });
            });
            
            markerManager.addMarker(marker, 1, 17);
            pois.push(poi);
        },
        
        // Eventhandler for when an marker is clicked
        markerClicked = function(marker, data) {
           var ne = mapObject.fromLatLngToDivPixel(mapObject.getBounds().getNorthEast());
           var sw = mapObject.fromLatLngToDivPixel(mapObject.getBounds().getSouthWest());
           var mp = mapObject.fromLatLngToDivPixel(marker.getPoint());
           mapObject.panBy(new google.maps.Size((ne.x - mp.x) - 120, (ne.y - mp.y) + 225));
           markerInfoWindow.find("h2").html(data.Name);
           markerInfoWindow.find(".text").html(data.Text);
           markerInfoWindow.show();
        },
        
        // Eventhandler for mouse over on a marker
        markerMouseOver = function(marker, data) {
            if (routeLabel.hasClass("active")) {
                routeLabel.hide();
            }
            jQuery("#mtgt_" + marker.id).attr("src", "/maps/images/red_icon_hover.png");
            mapObject.getPane(G_MAP_FLOAT_PANE).appendChild(marker.tooltip.get(0));
            var position = mapObject.fromLatLngToDivPixel(marker.getPoint());
            var iconAnchor = marker.getIcon().iconAnchor;
            var x = Math.round(position.x) + 11;
            var y = position.y - iconAnchor.y - 4;
            marker.tooltip.css({ "top": y + "px", "left": x + "px" });
        },
        
        // Eventhandler for mouse out on a marker
        markerMouseOut = function(marker, data) {
            if (routeLabel.hasClass("active")) {
                routeLabel.show();
            }
            jQuery("#mtgt_" + marker.id).attr("src", "/maps/images/red_icon.png");
            marker.tooltip.remove();
        },
        
        renderLabels = function() {
            // If it's the regular linemap, add all the routelabels.
            // this entire block should be handled and stored in the database.
            var labelpoints = [];
            
            labelpoints.push([new GLatLng(55.62179298063115, 13.16162109375), "820,832"]);
            labelpoints.push([new GLatLng(56.842963648401295, 15.018310546875), "841,842"]);
            labelpoints.push([new GLatLng(58.08949277309781, 14.65576171875), "777,830,832,862"]);
            labelpoints.push([new GLatLng(58.884780849473636, 17.1881103515625), "777,830,832,835,855,862"]);
            labelpoints.push([new GLatLng(57.6689107171251, 12.4365234375), "777,830,857"]);
            labelpoints.push([new GLatLng(59.98250201795759, 15.0732421875), "800"]);
            labelpoints.push([new GLatLng(58.12431960569376, 12.2113037109375), "800"]);
            labelpoints.push([new GLatLng(59.32198054010197, 15.9136962890625), "801"]);
            labelpoints.push([new GLatLng(59.09138238455912, 14.765625), "801"]);
            labelpoints.push([new GLatLng(59.57885104663186, 17.95166015625), "897,899"]);
            labelpoints.push([new GLatLng(57.42720958655339, 12.205810546875), "820"]);
            labelpoints.push([new GLatLng(58.7111891496366, 11.458740234375), "820"]);
            labelpoints.push([new GLatLng(57.016814017391105, 14.007568359375), "832"]);
            labelpoints.push([new GLatLng(56.32872090717995, 15.8642578125), "835"]);
            labelpoints.push([new GLatLng(55.83831352210821, 13.634033203125), "835"]);
            labelpoints.push([new GLatLng(57.1958078966064, 16.446533203125), "835"]);
            labelpoints.push([new GLatLng(58.10110549730587, 13.985595703125), "839"]);
            labelpoints.push([new GLatLng(59.18155722094253, 14.04052734375), "839"]);
            labelpoints.push([new GLatLng(59.08009382655441, 15.380859375), "844"]);
            labelpoints.push([new GLatLng(58.487951979600375, 15.216064453125), "855"]);
            labelpoints.push([new GLatLng(57.65127960812027, 15.0732421875), "857"]);
            labelpoints.push([new GLatLng(57.504020175224646, 13.809814453125), "862"]);
            labelpoints.push([new GLatLng(59.71763761778773, 11.2664794921875), "888"]);
            labelpoints.push([new GLatLng(60.834204246024875, 15.0732421875), "890"]);
            labelpoints.push([new GLatLng(60.1141451165239, 16.270751953125), "890"]);
            labelpoints.push([new GLatLng(60.32150850738404, 17.347412109375), "897"]);
            
            var minZoom = 7;
            var maxZoom = 17;

            for (i = 0; i < labelpoints.length; i++) {
                var str = labelpoints[i][1];

                str = str.replace(new RegExp(",", "g"), "<br />");
                var eLabel = new ELabel(labelpoints[i][0], str, "linjelabel_1");

                markerManager.addMarker(eLabel, minZoom, maxZoom);

                //add label to array, used for show/hide function
                labels.push(eLabel);
            }

            // add route custom labelpoints left
            var labelpoints = [];

            labelpoints.push([new GLatLng(61.554109444927185, 17.0947265625), "950 <img src='/maps/images/Ybusslogotyp.jpg'/>"]);
            labelpoints.push([new GLatLng(59.50087955346417, 16.138916015625), "866 <img src='/maps/images/flygturen-logo-large.gif'/>"]);
            labelpoints.push([new GLatLng(55.04061432771674, 11.77734375), "901 <img src='/maps/images/eurolines.jpg'/>"]);
            labelpoints.push([new GLatLng(53.592504809039376, 13.0078125), "901 <img src='/maps/images/bohemian-lines-logo.jpg'/>"]);



            var minZoom = 7;
            var maxZoom = 17;

            for (i = 0; i < labelpoints.length; i++) {
                var str = labelpoints[i][1];

                var eLabel = new ELabel(labelpoints[i][0], str, "linjelabel_2");

                markerManager.addMarker(eLabel, minZoom, maxZoom);

                //add label to array, used for show/hide function
                labels.push(eLabel);
            }

            // add route custom labelpoints right
            var labelpoints = [];

            labelpoints.push([new GLatLng(63.07984015900684, 18.3361816406255), "950 <img src='/maps/images/Ybusslogotyp.jpg'/>"]);
            labelpoints.push([new GLatLng(62.89271464700222, 15.66650390625), "950 <img src='/maps/images/Ybusslogotyp.jpg'/>"]);                

            var minZoom = 7;
            var maxZoom = 17;

            for (i = 0; i < labelpoints.length; i++) {
                var str = labelpoints[i][1];

                var eLabel = new ELabel(labelpoints[i][0], str, "linjelabel_3");

                markerManager.addMarker(eLabel, minZoom, maxZoom);

                //add label to array, used for show/hide function
                labels.push(eLabel);
            }
        },
        
        getData = function() {
            return data;
        }, 
        
        // Gets the current category
        getCurrentCategory = function() {
            return currentCategory;
        },
        
        getCurrentTabCategory = function() {
            return currentTabCategory;
        },
        
        // Sets the current category
        setCurrentCategory = function(value) {
            currentCategory = value;
        },
        
        getMapSelector = function() {
            return mapSelector;
        };
        
        // Start loading the map
        initializeMap(elementId, mapId);
        
        return {
          innerControl: mapObject,
          getCurrentCategory: getCurrentCategory,
          getCurrentTabCategory: getCurrentTabCategory,
          addCategoryTab: addCategoryTab,
          addSubCategory: addSubCategory,
          addRoute: addRoute,
          addPointOfInterest: addPointOfInterest,
          getData: getData,
          getMapSelector: getMapSelector
        };
    },
    
    // Adds a map to the current pages collection of maps
    addMap = function(elementId, mapId) {
        maps.push(new map(elementId, mapId));
    },
    
    // Gets all the maps currently viewed
    getMaps = function() {
        return maps;
    };
    
    return {
        init: init,
        addMap: addMap,
        getMaps: getMaps,
        BLUE_ICON: BLUE_ICON,
        RED_ICON: RED_ICON
    };
}();

jQuery(function() {
    swebusMaps.init();
});
