﻿var cameraCount = 0;
var cameraLastUpdateCenter;
var cameraLastUpdateZoom;
var cameraRegistry = new Array();
var cameraUpdatesType = "all";
var defaultCameraIconURL = "images/cctv.png";

var incidentLastUpdateCenter;
var incidentLastUpdateZoom;
var incidentLayerNames = new Array("incidentsLayer", "congestionLayer", "constructionLayer", "detourLayer", "weatherLayer", "specialEventLayer");
var incidentRegistry = new Array();
var incidentUpdatesTimeout;
var incidentUpdatesType = "all";
var incidentLayersLoaded;

function ClearAllIncidentLayers() {
    for (var i = 0; i < incidentLayerNames.length; i++) {
        if (MapLayers[incidentLayerNames[i]]) { MapLayers[incidentLayerNames[i]].clear(); }
        incidentLayersLoaded[incidentLayerNames[i]] = false;
    }
    ClearRegistry(incidentRegistry);
}

function GetCameraBalloonContent(cameraDescription, cameraImageURL) {
    /// <summary>Returns the content of a camera balloon with the balloon div width and the camera image size adjusted, based on the size of the map, to not display any of the image "off the map"</summary>
    var ID = cameraImageURL.replace("http://", "");
    while (ID.indexOf("/") != -1) { ID = ID.replace("/", ""); }
    while (ID.indexOf(".") != -1) { ID = ID.replace(".", ""); }
    while (ID.indexOf(" ") != -1) { ID = ID.replace(" ", ""); }
    
    var balloonWidth = 300, imageWidth = 297, imageHeight = 225;
    var maxBalloonWidth = Math.floor(map.getWidth() / 2);
    var maxImageHeight = Math.floor(map.getHeight() / 2) - 43 - 30;  // 43 = dock height, 30 = balloon description area
    if (balloonWidth > maxBalloonWidth) {
        balloonWidth = maxBalloonWidth;
        imageWidth = balloonWidth - 3;
        imageHeight = Math.floor(imageWidth * 0.76);
    }
    if (imageHeight > maxImageHeight) {
        imageHeight = maxImageHeight;
        imageWidth = Math.floor(imageHeight * 1.32);
        balloonWidth = imageWidth + 3;
    }

    var balloonContent = '<div class="mapBalloon" style="width:' + balloonWidth + 'px">' +
        '<strong>' + cameraDescription + '</strong><br />' + 
        '<div id="lc' + ID + '" style="display:block">Loading camera image...</div>' +
        '<img onload="HideCameraImageLoading(\'' + ID + '\');" class="cameraImage" width="' + imageWidth + 'px" height="' + imageHeight + 'px" src="' + cameraImageURL + '" />' +
        '</div>';
    return balloonContent;
}

function GetShields() {
    var gspArray = new Array();
    gspArray[0] = "images/gsp.png";
    gspArray[1] = new Array(39.00559, -74.8702);
    gspArray[2] = new Array(39.61214, -74.426);
    gspArray[3] = new Array(40.25002, -74.0819);
    gspArray[4] = new Array(40.50277, -74.3012);
    gspArray[5] = new Array(40.80421, -74.1848);
    gspArray[6] = new Array(41.05415, -74.0657);
    
    /*
    gspArray[1] = new Array(39.19267515, -74.71106521);
    gspArray[2] = new Array(39.00559213, -74.87022106);
    gspArray[3] = new Array(39.30532206, -74.61799903);
    gspArray[4] = new Array(39.61214249, -74.42597494);
    gspArray[5] = new Array(39.77252763, -74.24519619);
    gspArray[6] = new Array(39.99572714, -74.20713865);
    gspArray[7] = new Array(40.25002074, -74.08192636);
    gspArray[8] = new Array(40.48854301, -74.30235644);
    gspArray[9] = new Array(40.70572677, -74.24566465);
    gspArray[10] = new Array(40.80420764, -74.18480402);
    gspArray[11] = new Array(40.90766632, -74.09971476);
    gspArray[12] = new Array(40.98112628, -74.07105532);
    gspArray[13] = new Array(41.05414774, -74.06573329);
    */

    var njtaArray = new Array();
    njtaArray[0] = "images/njtp.png";

    njtaArray[1] = new Array(39.6857547, -75.4471839);
    njtaArray[2] = new Array(40.0964608, -74.7303578);
    njtaArray[3] = new Array(40.5910884, -74.2367373);
    njtaArray[4] = new Array(40.8385709, -74.0192852);
    
    /*
    njtaArray[1] = new Array(39.6857547, -75.44718385);
    njtaArray[2] = new Array(39.8600825, -75.0725526);
    njtaArray[3] = new Array(40.09646078, -74.73035777);
    njtaArray[4] = new Array(40.34770669, -74.4748557);
    njtaArray[5] = new Array(40.54148603, -74.30492605);
    njtaArray[6] = new Array(40.63566933, -74.20933987);
    njtaArray[7] = new Array(40.71372323, -74.1412503);
    njtaArray[8] = new Array(40.79615196, -74.08043831);
    njtaArray[9] = new Array(40.83857088, -74.0192852);
    njtaArray[10] = new Array(40.77045552, -74.06272563);
    */

    var acxArray = new Array();
    acxArray[0] = "images/acx.png";
    acxArray[1] = new Array(39.4323789, -74.585355);
    acxArray[2] = new Array(39.7671828, -75.0472918);

    /*
    acxArray[0] = "images/acx.png";
    acxArray[1] = new Array(39.37494319, -74.47696547);
    acxArray[2] = new Array(39.43237887, -74.58535499);
    acxArray[3] = new Array(39.51203539, -74.68453718);
    acxArray[4] = new Array(39.65032634, -74.8735677);
    acxArray[5] = new Array(39.7671828, -75.04729178);
    acxArray[6] = new Array(39.37441986, -74.4405563);
    */
    
    var layer = MapLayers['shieldsLayer'];
    layer.clear();

    for (var i = 1; i < gspArray.length; i++) {
        new Telogis.GeoBase.MapLayers.ImageObject({
            id: 'gsp' + i,
            layer: layer,
            location: { lat: gspArray[i][0], lon: gspArray[i][1] },
            src: gspArray[0]
        });
    }

    for (var i = 1; i < njtaArray.length; i++) {
        new Telogis.GeoBase.MapLayers.ImageObject({
            id: 'njta' + i,
            layer: layer,
            location: { lat: njtaArray[i][0], lon: njtaArray[i][1] },
            src: njtaArray[0]
        });
    }

    for (var i = 1; i < acxArray.length; i++) {
        new Telogis.GeoBase.MapLayers.ImageObject({
            id: 'acx' + i,
            layer: layer,
            location: { lat: acxArray[i][0], lon: acxArray[i][1] },
            src: acxArray[0]
        });
    }
}

function HandleMapIcon( sender, args ) {
    var commandName = args.Command.get_name();
    switch (commandName) {
        case "ToggleCamera": ToggleLayer("camerasLayer"); break;
        case "ToggleIncident": ToggleLayer("incidentsLayer"); break;
        case "ToggleCongestion": ToggleLayer("congestionLayer"); break;
        case "ToggleConstruction": ToggleLayer("constructionLayer"); break;
        case "ToggleDetour": ToggleLayer("detourLayer"); break;
        case "ToggleWeather": ToggleLayer("weatherLayer"); break;
        case "ToggleSpecialEvent": ToggleLayer("specialEventLayer"); break;
        case "ToggleSatellite": ToggleLayer("satelliteLayer"); break;
        case "ToggleTraffic": ToggleLayer("trafficLayer"); break;
    }
    args.Command.set_state(args.Command.get_state() == 1 ? 2 : 1);
}

function HideCameraImageLoading(ID) {
    $("#lc" + ID).hide();
}

function IncidentLayersNeedRefresh() {
    if (incidentLayersLoaded == null) {
        incidentLayersLoaded = new Object();
        for (var i = 0; i < incidentLayerNames.length; i++) {
            incidentLayersLoaded[incidentLayerNames[i]] = false;
        }
    }

    var refreshNeeded = false;
    for (var i = 0; i < incidentLayerNames.length; i++) {
        if (MapLayers[incidentLayerNames[i]]) {
            if (MapLayers[incidentLayerNames[i]].isVisible() && incidentLayersLoaded[incidentLayerNames[i]] == false) {
                refreshNeeded = true;
                break;
            }
        }
    }
    return refreshNeeded;
}

function LogError(xmlDetails, sourcePage) {
    /*
    AjaxCall(null, "services/MapServiceProxy.asmx/WriteToErrorLog",
        "{'sourcePage':'" + sourcePage + "','xmlDetails':'" + xmlDetails + "'}",
        null, null, function(result) { }, function(xhr, statusText, thrownError) { });
        */
}

function ToggleBaseMap(sender, args) {
    map.getTileLayer().toggleVisibility();
    args.Command.set_state(args.Command.get_state() == 1 ? 2 : 1);
}

function ToggleLayer(layerName) {
    MapLayers[layerName].toggleVisibility();
    if (MapLayers[layerName].isVisible()) {
        switch (layerName) {
            case 'camerasLayer':
                //if (cameraUpdatesType != "xml") { UpdateCameras(); } // Commented out as workaround for Telogis issue
                // Next line added as workaround for Telogis issue - run UpdateCameras() for all types, including xml
                UpdateCameras();
                break;
            case 'incidentsLayer':
            case 'congestionLayer':
            case 'constructionLayer':
            case 'detourLayer':
            case 'weatherLayer':
            case 'specialEventLayer':
                UpdateIncidents();
                break;
        }
    }
    else if (layerName == "camerasLayer") {
        // Workaround for Telogis issue - blank the layer when hidden
        MapLayers['camerasLayer'].loadXML("<blank></blank>");
    }
}

// == Ajax Calls ========================================================================================================

function UpdateCameras() {
    switch (cameraUpdatesType) {
        case 'bylatlon':
            if (cameraLastUpdateCenter == null || cameraLastUpdateZoom == null ||
                map.getCenter().lat != cameraLastUpdateCenter.lat ||
                map.getCenter().lon != cameraLastUpdateCenter.lon ||
                map.getZoomIndex() != cameraLastUpdateZoom) {
                UpdateCamerasByLatLon();
            }
            break;
        case 'xml':
            AjaxCallWithRetry(null, 'services/MapServiceProxy.asmx/GetFullCameraListXML', null, null, null,
                UpdateCamerasXML, UpdateCamerasXMLError, 3);
            break;
        default:
            UpdateCamerasAll();
            break;
    }
    
    if (cameraUpdatesType == "bylatlon" && !map['CamerasCallbackListener']) {
        map.addListener({
            id: 'CamerasCallbackListener',
            setMap: function(map) { },
            update: function(updateType) {
                if (updateType == Map.UPDATE_END_PAN || updateType == Map.UPDATE_REDRAW || updateType == Map.UPDATE_SIZE) {
                    UpdateCameras();
                }
            }
        });
    }
}

function UpdateCamerasAll() {
    if (MapLayers['camerasLayer'].isVisible() && map.getZoomIndex() > 5) {
        AjaxCall("POST", "services/MapServiceProxy.asmx/GetFullCameraList", null,
            "application/json; charset=utf-8", "json",
            function(result) {
                UpdateCamerasCallback(result);
            },
            function(xhr, ajaxOptions, thrownError) {
                alert("AJAX error in UpdateCameras");
                alert(xhr.status);
                alert(thrownError);
            }
        );
    }
}

function UpdateCamerasByLatLon() {
    if (MapLayers['camerasLayer'].isVisible() && map.getZoomIndex() > 5) {
        var upperLeft = GetMapUpperLeft();
        var lowerRight = GetMapLowerRight();
        AjaxCall("POST", "services/MapServiceProxy.asmx/GetCamerasByLatLon",
            "{'westLon':'" + upperLeft.lon + "', 'northLat':'" + upperLeft.lat + "', 'eastLon':'" + lowerRight.lon + "', 'southLat':'" + lowerRight.lat + "', 'zoom':'" + map.getZoomIndex() + "'}",
            "application/json; charset=utf-8", "json",
            function(result) {
                UpdateCamerasCallback(result);
                cameraLastUpdateCenter = new Telogis.GeoBase.LatLon(map.getCenter().lat, map.getCenter().lon);
                cameraLastUpdateZoom = map.getZoomIndex();
            },
            function(xhr, ajaxOptions, thrownError) {
                alert("AJAX error in UpdateCameras");
                alert(xhr.status);
                alert(thrownError);
            }
        );
    }
}

function UpdateIncidents() {
    switch (incidentUpdatesType) {
        case 'bylatlon':
            if (IncidentLayersNeedRefresh() ||
                incidentLastUpdateCenter == null || incidentLastUpdateZoom == null ||
                map.getCenter().lat != incidentLastUpdateCenter.lat ||
                map.getCenter().lon != incidentLastUpdateCenter.lon ||
                map.getZoomIndex() != incidentLastUpdateZoom) {
                ClearAllIncidentLayers();
                UpdateIncidentsByLatLon();
            }
            break;
        default:
            UpdateIncidentsAll();
            break;
    }

    if (incidentUpdatesType == "bylatlon" && !map['IncidentsCallbackListener']) {
        map.addListener({
            id: 'IncidentsCallbackListener',
            setMap: function(map) { },
            update: function(updateType) {
                //if (updateType == Map.UPDATE_END_PAN || updateType == Map.UPDATE_REDRAW || updateType == Map.UPDATE_SIZE) {
                if (updateType & Map.UPDATE_END_PAN || (updateType & Map.UPDATE_PAN && !map.isDragging()) || updateType == Map.UPDATE_REDRAW || updateType == Map.UPDATE_SIZE) {
                    //alert("IncidentsCallbackListener = Update type: " + updateType);
                    ClearAllIncidentLayers();
                    UpdateIncidents();
                }
            }
        });
    }

    if (incidentUpdatesTimeout != null) { clearTimeout(incidentUpdatesTimeout); }
    incidentUpdatesTimeout = setTimeout("ClearAllIncidentLayers(); UpdateIncidents();", 60 * 1000);
}

function UpdateIncidentsAll() {
    if (map.getZoomIndex() > 5) {
        AjaxCall("POST", "services/MapServiceProxy.asmx/GetIncidentList", null,
            "application/json; charset=utf-8", "json",
            function(incidents) {
                UpdateIncidentsCallback(incidents);
            },
            function(xhr, ajaxOptions, thrownError) {
                alert("AJAX error in UpdateIncidentsAll");
                alert(xhr.status);
                alert(thrownError);
            }
        );
    }
}

function UpdateIncidentsByLatLon() {
    if (map.getZoomIndex() > 5) {
        var upperLeft = GetMapUpperLeft();
        var lowerRight = GetMapLowerRight();
        AjaxCall("POST", "services/MapServiceProxy.asmx/GetIncidentsByLatLon",
            "{'westLon':'" + upperLeft.lon + "', 'northLat':'" + upperLeft.lat + "', 'eastLon':'" + lowerRight.lon + "', 'southLat':'" + lowerRight.lat + "'}",
            "application/json; charset=utf-8", "json",
            function(incidents) {
                UpdateIncidentsCallback(incidents);
                incidentLastUpdateCenter = new Telogis.GeoBase.LatLon(map.getCenter().lat, map.getCenter().lon);
                incidentLastUpdateZoom = map.getZoomIndex();
            },
            function(xhr, ajaxOptions, thrownError) {
                alert("AJAX error in UpdateIncidents\nStatus: " + xhr.status + "\nError: " + thrownError);
            }
        );
    }
}

// == Ajax Callbacks ====================================================================================================

function UpdateCamerasCallback(cameras) {
    var count = 0;
    MapLayers['camerasLayer'].clear();
    ClearRegistry(cameraRegistry);
    //var start = new Date().getTime();
    $(cameras.d).each(function() {
        if (cameraCount > 0 && count >= cameraCount) {
            return false;
        }

        var cameraIconURL = defaultCameraIconURL;
        if (this.IconURL) {
            cameraIconURL = this.IconURL;
        }

        cameraRegistry[count++] = CreateImageObject('cam' + this.ID, MapLayers['camerasLayer'],
            new Telogis.GeoBase.LatLon(this.Lat, this.Lon), cameraIconURL,
            GetCameraBalloonContent(this.Description, this.CameraImageURL), false);
    });
    //alert("Cameras took " + (new Date().getTime() - start) + " milliseconds.");
}

function UpdateCamerasXML(result) {
    MapLayers['camerasLayer'].loadXML(result.d);
}

function UpdateCamerasXMLError(xhr, textStatus, thrownError) {
    AjaxErrorHandler("services/MapServiceProxy.asmx/GetFullCameraListXML", xhr, textStatus, thrownError,
        "UpdateCamerasXML(result);",
        "UpdateCamerasXMLError(xhr, textStatus, thrownError);"
    );
}

function UpdateIncidentsCallback(incidents) {
    var count = 0;
    var iconURL = "";
    var layerName = "";

    $(incidents.d).each(function() {
        if (this.IconURL.toLowerCase().indexOf("incident") != -1) {
            layerName = 'incidentsLayer'
        }
        else if (this.IconURL.toLowerCase().indexOf("congestion") != -1) {
            layerName = 'congestionLayer'
        }
        else if (this.IconURL.toLowerCase().indexOf("construction") != -1) {
            layerName = 'constructionLayer'
        }
        else if (this.IconURL.toLowerCase().indexOf("detour") != -1) {
            layerName = 'detourLayer'
        }
        else if (this.IconURL.toLowerCase().indexOf("weather") != -1) {
            layerName = 'weatherLayer'
        }
        else if (this.IconURL.toLowerCase().indexOf("specialevent") != -1) {
            layerName = 'specialEventLayer'
        }
        else {
            layerName = 'incidentsLayer'
        }

        // Put on incidentsLayer if specific layerName not found
        if (!MapLayers[layerName]) {
            layerName = 'incidentsLayer';
        }

        if (MapLayers[layerName].isVisible()) {
            // MapLayersWrapper.layers[layerName].icons[this.ID] =
            incidentLayersLoaded[layerName] = true;
            incidentRegistry[count++] = CreateImageObject('inc' + this.ID, MapLayers[layerName],
                new Telogis.GeoBase.LatLon(this.Lat, this.Lon), this.IconURL,
                '<div class="mapBalloon">' + this.Description + '</div>', true);
        }
    });

    // Mark layers just loaded
    for (var i = 0; i < incidentLayerNames.length; i++) {
        if (MapLayers[incidentLayerNames[i]]) {
            if (MapLayers[incidentLayerNames[i]].isVisible()) {
                incidentLayersLoaded[incidentLayerNames[i]] = true;
            }
        }
    }
}