﻿dojo.require("esri.map");
dojo.require("esri.toolbars.draw");
dojo.require("esri.toolbars.navigation");
dojo.require("esri.tasks.locator");
dojo.require("esri.tasks.query");
dojo.require("esri.tasks.geometry");
dojo.require("dijit.dijit");
dojo.require("dijit.dijit-all");
dojo.require("dijit.Tooltip");
dojo.require("dijit.TitlePane");
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.TabContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.LayoutContainer");
dojo.require("dijit.form.FilteringSelect");
//dojo.require("dojox.layout.ResizeHandle");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dojox.layout.ExpandoPane");
dojo.require("dojox.layout.FloatingPane");
dojo.require("dijit.form.Button");
dojo.require("dijit.Toolbar");
dojo.require("dijit.form.Slider");
dojo.require("dijit.form.TextBox");
dojo.require("dojo.fx.easing");
dojo.require("dojo.parser");
dojo.require("dojox.lang.functional");
dojo.require("dojox.lang.functional.lambda");
dojo.require("dojox.lang.functional.curry");
dojo.require("dojox.lang.functional.fold");
//dojo.require("dojox.charting.action2d.MoveSlice");
//dojo.require("dojox.charting.Chart2D");
//dojo.require("dojox.charting.action2d.Highlight");
//dojo.require("dojox.charting.action2d.Tooltip");
//dojo.require("dojox.charting.themes.MiamiNice");
//dojo.require("dojox.charting.widget.Legend");

function init() {

    // Set up proxy page to handle large results.  Path must be edited in the proxy.config file.
    // For more info on proxy pages, go to:
    // http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jshelp/ags_proxy.htm
    esriConfig.defaults.io.proxyUrl = "proxy.ashx";
    esriConfig.defaults.io.alwaysUseProxy = false;

    var startExtent = new esri.geometry.Extent(XMin, YMin, XMax, YMax, new esri.SpatialReference({ wkid: parseInt(refScale_baseMap) }));
    var layersLoaded = 0;  //varible to keep track of when all layers have been loaded.
    loading = dojo.byId("loadingImg");  //loading image id

    esriConfig.defaults.map.slider = { left: "30px", top: "30px", width: null, height: "200px" };
    esriConfig.defaults.map.sliderlabel = { tick: 5, labels: null, style: "width:2em; font-family:Verdana; font-size:75%;" };

    map = new esri.Map("mapDiv", { nav: false, extent: startExtent });

    dojo.connect(map, "onLoad", showLoading);
    dojo.connect(map, "onZoomStart", showLoading);
    dojo.connect(map, "onZoomEnd", endLoading);
    dojo.connect(map, "onMouseMove", showCoordinates);
    dojo.connect(map, "onClick", displayPictometry);
    dojo.connect(map, "onMouseDown", checkZoom);
    dojo.connect(map, "onPanStart", onPanStart);
    dojo.connect(map, "onPanEnd", onPanEnd);
    dojo.connect(map, "onPan", onPan);

    // tb is toolbar for location query
    tb = new esri.toolbars.Draw(map);
    dojo.connect(tb, "onDrawEnd", addGraphic);

    // tb_measure is toolbar for measure
    tb_measure = new esri.toolbars.Draw(map);
    dojo.connect(tb_measure, "onDrawEnd", addMeasure);

    dojo.connect(dijit.byId("mapDiv"), "resize", resizeMap);

    //Base Map Service
    if (isBaseMapTiled) {
        tiledMapServiceLayer = new esri.layers.ArcGISTiledMapServiceLayer(baseMap, { id: "Base_Map", visible: true });
        map.addLayer(tiledMapServiceLayer);
        dojo.connect(tiledMapServiceLayer, "onUpdate", hideLoading);
        addToTOC(tiledMapServiceLayer, false);
    }
    else {
        dynamicMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(baseMap, { id: "Base_Map", visible: true });
        map.addLayer(dynamicMapServiceLayer);
        dojo.connect(dynamicMapServiceLayer, "onUpdate", hideLoading);
        addToTOC(dynamicMapServiceLayer, true);
    }

    //Oerlay Map Service
    overlayMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(overlayMap, { id: "Overlay_Map", visible: true });
    map.addLayer(overlayMapServiceLayer);
    dojo.connect(overlayMapServiceLayer, "onUpdate", hideLoading);
    addToTOC(overlayMapServiceLayer, true);

    //Address Locator Service
    locator = new esri.tasks.Locator(addressLocator);
    dojo.connect(locator, "onAddressToLocationsComplete", showResults);

    //Geometry Service
    geometryService = new esri.tasks.GeometryService(geoService);

    dojo.connect(geometryService, "onAreasAndLengthsComplete", outputAreaAndLength);
    dojo.connect(geometryService, "onLengthsComplete", outputDistance);

    navToolbar = new esri.toolbars.Navigation(map);
    dojo.connect(navToolbar, "onExtentHistoryChange", extentHistoryChangeHandler);

    activeTool = "pan";
    if (dojo.isIE) { map.setMapCursor("url(cursors/pan.cur"); }

    map.enableMapNavigation();
    map.showZoomSlider();
    map.enableKeyboardNavigation();
    map.enableShiftDoubleClickZoom();
    map.enableDoubleClickZoom();
    map.enableRubberBandZoom();
    map.enableScrollWheelZoom();
    map.enablePan();

//    dojo.connect(map, "onExtentChange", function(extent, delta, leveChange, lod) {
//        addClusteredPoints(lotsOfPoints, map, lod.level + 2, extent);
//    });

    function extentHistoryChangeHandler() {
        //dijit.byId("zoomprev").disabled = navToolbar.isFirstExtent();
        //dijit.byId("zoomnext").disabled = navToolbar.isLastExtent();
        var scale = esri.geometry.getScale(map.extent, map.width, refScale_baseMap);
        dojo.byId("scale").innerHTML = "1:" + roundNumber(scale);
    }

    function showCoordinates(evt) {
        //get mapPoint from event
        var mp = evt.mapPoint;
        //display mouse coordinates
        if (refScale_baseMap == 4326) {
            dojo.byId("info").innerHTML = roundNumber(mp.x, 4) + ", " + roundNumber(mp.y, 4);
        }
        else {
            dojo.byId("info").innerHTML = roundNumber(mp.x, 0) + ", " + roundNumber(mp.y, 0);
        }
    }

    function showLoading() {
        esri.show(loading);
        map.disableMapNavigation();
        map.hideZoomSlider();
        map.infoWindow.hide();
        //if (symbolClustering) { map.graphics.clear(); }
    }

    function hideLoading() {
        layersLoaded++;
        if (layersLoaded === map.layerIds.length) {
            esri.hide(loading);
            map.enableMapNavigation();
            map.showZoomSlider();
            layersLoaded = 0;
        }
        var lpane = dojo.byId("leftPane");
        if (lpane.style.visibility != "visible") {
            lpane.style.visibility = "visible";
        }
        var rpane = dojo.byId("bcRight");
        if (rpane.style.visibility != "visible") {
            rpane.style.visibility = "visible";
        }
    }

    function endLoading() {
        esri.hide(loading);
        map.enableMapNavigation();
        map.showZoomSlider();
        var elm = dojo.byId(activeTool);
        makeIconActive(elm);
    }

    function checkZoom(evt) {
        if (activeTool == "zoomin") { map.disablePan(); }
        if (activeTool == "zoomout") { map.disablePan(); }
        if (activeTool == "pan") { map.enablePan(); }
    }

    function onPanStart(ext, startPt) {
        if (dojo.isIE) { map.setMapCursor("url(cursors/panning.cur"); }
    }

    function onPan(ext, dlta) {
        if (dojo.isIE) { map.setMapCursor("url(cursors/panning.cur"); }
    }

    function onPanEnd(ext, endPt) {
        if (dojo.isIE) { map.setMapCursor("url(cursors/pan.cur"); }
    }

    loadLocationWidget();
    loadBufferWidget();
    loadDateWidget();
    dijit.byId("tabs").resize();
    hideAdvancedDates();
    if (showPictometryButton == true) {
        pictometryInit();
    }
}

//Handle resize of browser
function resizeMap() {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function() {
        map.resize();
        map.reposition();
    }, 800);
}

function initFunctionality(map, points) {
    var lotsOfPoints = points;
    addClusteredPoints(lotsOfPoints, map, 2, map.extent);
    dojo.connect(map, "onZoomStart", function() {
        map.graphics.clear();
    });
    dojo.connect(map, "onExtentChange", function(extent, delta, leveChange, lod) {
        addClusteredPoints(lotsOfPoints, map, lod.level + 2, extent);
    });
}

function addClusteredPoints(points, map, level, extent) {
    var df = dojox.lang.functional;
    //Get current tiling scheme.  This restriction can be removed.  
    //The only thing required is origin, array of grid pixel resolution, & grid pixel size
    var tileInfo = map.getLayer(map.layerIds[0]).tileInfo;

    //lambda function to map points to tile space
    var toTileSpaceF = df.lambda("point, tileWidth, tileHeight, oPoint "
            + "-> [Math.floor((oPoint.y - point.y)/tileHeight),Math.floor((point.x-oPoint.x)/tileWidth), point]");  

    var levelResolution = tileInfo.lods[level].resolution;
    var width = levelResolution * tileInfo.width;
    var height = levelResolution * tileInfo.height;

    //predefine width, height, origin point for toTileSpaceF function
    var toTileSpace = df.partial(toTileSpaceF, df.arg, width, height, tileInfo.origin);  
    var extentTileCords = df.map([new esri.geometry.Point(extent.xmin, extent.ymin), new esri.geometry.Point(extent.xmax, extent.ymax)], toTileSpace);  //map extent corners to tile sapce
    var minRowIdx = extentTileCords[1][0];
    var maxRowIdx = extentTileCords[0][0];
    var minColIdx = extentTileCords[0][1];
    var maxColIdx = extentTileCords[1][1];

    var pointSymbol = {
        "single": new esri.symbol.PictureMarkerSymbol("images/CircleBlue24.png", 24, 24),
        "grouped": new esri.symbol.PictureMarkerSymbol("images/CircleRed32.png", 32, 32)
    };

    //points to tiles
    if (!levelPointTileSpace[level]) {
        var pointsTileSpace = df.map(points, toTileSpace);  //map all points to tilespace
        var tileSpaceArray = [];
        dojo.forEach(pointsTileSpace, function(tilePoint, ptIndex) {  //swizel points[row,col,point] to row[col[points[]]]
            if (tileSpaceArray[tilePoint[0]]) {
                var y = tileSpaceArray[tilePoint[0]];
                if (y[tilePoint[1]]) {
                    y[tilePoint[1]].push(tilePoint[2]);
                } else {
                    y[tilePoint[1]] = tilePoint[1];
                    y[tilePoint[1]] = [tilePoint[2]];
                }
            } else {
                var y = tileSpaceArray[tilePoint[0]] = [];
                y[tilePoint[1]] = tilePoint[1];
                y[tilePoint[1]] = [tilePoint[2]];
            }
        });
        //once this has been computed store this in a level array
        levelPointTileSpace[level] = tileSpaceArray;  
    }
    var tileCenterPointF = df.lambda("cPt,nextPt->{x:(cPt.x+nextPt.x)/2,y:(cPt.y+nextPt.y)/2}");

    dojo.forEach(levelPointTileSpace[level], function(row, rowIndex) {
        if ((rowIndex >= minRowIdx) & (rowIndex <= maxRowIdx)) {
            dojo.forEach(row, function(col, colIndex) {
                if (col) {
                    if ((colIndex >= minColIdx) & (colIndex <= maxColIdx)) {
                        var pointsToBeAdded = [];
                        if (col.length > 2) {
                            var tileCenterPoint = df.reduce(col, tileCenterPointF);
                            map.graphics.add(new esri.Graphic(new esri.geometry.Point(tileCenterPoint.x, tileCenterPoint.y), pointSymbol.grouped));
                            (dojo.isIE) ? null : map.graphics.add(new esri.Graphic(new esri.geometry.Point(tileCenterPoint.x, tileCenterPoint.y), new esri.symbol.TextSymbol(col.length).setOffset(0, -3)));
                        }
                        else {
                            dojo.forEach(col, function(point) {
                                map.graphics.add(new esri.Graphic(new esri.geometry.Point(point), pointSymbol.single));
                            });
                        }
                    }
                }
            });
        }
    });
}

     
