var tmrTimer = null;

var boolShowDisclaimerStartUp = false;
var boolChangeMap = false;
var boolMapResize = false;

function acceptDisclaimer(pNumMapID)
{
    closeDisclaimerPopUp();

    var strUrl = "./jsp/updateDisclaimers.jsp";
    var strUrlParams = "mapID=" + pNumMapID + "&lang=" + strLang;

    // Create a new XML HTTP object for AJAX operation.
    var oTempXmlHttp = getNewXmlHTTPObject();

    if (!isXmlHTTPNull(oTempXmlHttp))
        doXMLRequest(oTempXmlHttp, strUrl, strUrlParams, "post", false, "application/x-www-form-urlencoded");

    // Activate the map hierarchy click event.
    if (strSelectedMapRowName.trim().length > 0)
        document.getElementById(strSelectedMapRowName).onclick();

    boolShowDisclaimerStartUp = false;

    // Check to see if the disclaimer is first shown when the user has loaded the application. When the disclaimer is first shown,
    // the OpenLayers map object contains no layers.
    if (objMap.getNumLayers() == 0)
    {
        boolInitializingMap = true;

        // Get the map info.
        var objResponse = getMap(pNumMapID);
        if ((objResponse != null) && (objResponse != undefined))
        {
            // Display the map info and return an array with the map title and map layers.
            var arryResult = processMap(objResponse);

            // Perform a WMS request and add the layer(s) to the map.
            objMap.addLayers([doWMS(arryResult[0], arryResult[1], "")]);

            // Set the center and zoom for the map.
            doResetMap();
        }

        // Show the sidebar.
        showSidebar();

        numMapID = pNumMapID;

        boolInitializingMap = false;
    }
    else
    {
        // Get the new map.
        changeMap(pNumMapID);
    }
}

function closeDisclaimerPopUp()
{
    // Check to see if the disclaimer is first shown when the user has loaded the application.
    if (boolShowDisclaimerStartUp)
    {
        boolShowDisclaimerStartUp = false;

        // Displayed an "access denied" page.
        window.location.replace("./denied.jsp?lang=" + strLang);
    }

    // Remove the div.
    removePopUp("divDisclaimerPopUp");

    boolDisclaimerVisible = false;
}

function getMapDataXML(pNumMapID, pScale, pStrExcludedLayers)
{
    var strUrl = "./jsp/showMap.jsp";
    var strUrlParams = "mapID=" + pNumMapID + "&startup=" + boolInitializingMap;

    if ((pStrExcludedLayers != null) && (pStrExcludedLayers.length > 0))
        strUrlParams += "&excludeLayers=" + pStrExcludedLayers;

    if (pScale != null)
        strUrlParams += "&scale=" + pScale;

    // Add the language parameter.
    strUrlParams += "&lang=" + strLang;

    // Create a new XML HTTP object for AJAX operation.
    var oTempXmlHttp = getNewXmlHTTPObject();

    if (!isXmlHTTPNull(oTempXmlHttp))
    {
        logMsg("Retrieving view data. url: " + encodeURIComponent(strUrl + "?" + strUrlParams), "info", "openLayersMap.js (getMapDataXML)");
        doXMLRequest(oTempXmlHttp, strUrl, strUrlParams, "post", false, "application/x-www-form-urlencoded");

        var strResponse = oTempXmlHttp.responseText;
    }

    // Return the root object.
    if (navigator.appName == "Microsoft Internet Explorer")
    {
        var strData = oTempXmlHttp.responseText;

        var xmlDoc = null;
        try
        {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async = "false";
            xmlDoc.loadXML(strData);
        }
        catch(e) {alert(e.message)}

        return xmlDoc.getElementsByTagName("map")[0];
    }
    else
        return oTempXmlHttp.responseXML.getElementsByTagName("map")[0];
}

function doGetFeatureInfo(pXY, pStrPopUpTitle)
{
    // Add the filters to the WMS request.
    var strFilters = getFilters();

    // Add the Mapit layer if it is selected.
    if (isMapitSelected())
    {
        if (strFilters.trim().length > 0)
            strFilters += "|";

        // Update the filter parameter.
        strFilters += getMapitfilter();
    }

    var strUrl = "./jsp/showFeatureInfo.jsp";
    var strUrlParams = "query_layers=" + strQueryLayer + "&layers=" + strQueryLayer + "&filters=" + strFilters.replace(/\s+/g, "") + "&bbox=" + objMap.getExtent().toBBOX() + "&width=" + objMap.getSize().w + "&height=" + objMap.getSize().h + "&x=" + pXY.x + "&y=" + pXY.y + "&title=" + strQueryLayerTitle.replace(/>/g, "^gt^").replace(/</g, "^lt^").replace(/\//g, "%2F") + "&lang=" + strLang;

    objMap.div.style.cursor = "wait";

    // Create a new XML HTTP object for AJAX operation.
    var oTempXmlHttp = getNewXmlHTTPObject();

    // Process the AJAX request.
    if (!isXmlHTTPNull(oTempXmlHttp))
    {
        logMsg("Perform GetFeatureInfo request. url: " + encodeURIComponent(strUrl + "?" + strUrlParams), "info", "openLayersMap.js (doGetFeatureInfo)");
        doXMLRequest(oTempXmlHttp, strUrl, strUrlParams, "post", true, "application/x-www-form-urlencoded", "showFeatureInfoCallback('" + pStrPopUpTitle + "', pObjXmlHTTP)");
    }
}

function showFeatureInfoCallback(pStrPopUpTitle, pObjXmlHTTP)
{
    //logMsg("*** result: " + pObjXmlHTTP.responseText, "info", "openLayersMap.js (doGetFeatureInfo)");

    // Create a div containing the results.
    var objDivGetFeatureInfoPopUp = createDivPopUp(pStrPopUpTitle, pObjXmlHTTP.responseText, "divGetFeatureInfoPopUp", "popUpGetFeatureInfoWindow", true, false)

    // Size the popup window to it contents.
    sizeDivPopUpToContent(objDivGetFeatureInfoPopUp);

    // Position the div.
    centerObjectWithin(objDivGetFeatureInfoPopUp, (document.body || window));

    objMap.div.style.cursor = "default";
}

function doLayerEvent(event, pStrAction)
{
    if (pStrAction.toUpperCase() == "LOADSTART")
    {
        var strLayers = event.object.params["LAYERS"];
        var strFilters = event.object.params["FILTERS"];
        var strWMSUrl = event.object.getURL(event.object.getExtent());

        // Log the WMS request.
        logMsg("WMS layers: " + strLayers, "info", "openLayersMap.js(doLayerEvent)");
        logMsg("WMS filters: " + strFilters, "info", "openLayersMap.js (doLayerEventdoLayerEvent)");
        logMsg("WMS url: " + encodeURIComponent(strWMSUrl), "info", "openLayersMap.js (doLayerEvent)");

        showLoadingModal();
    }
    else if (pStrAction.toUpperCase() == "LOADEND")
    {
        // Hide the modal progress bar.
        removeElement("divLoadingMapModal");

        document.getElementById("divLoading").style.display = "none";
    }

    // Position the loading animation.
    centerObjectWithin(document.getElementById("divLoading"), document.getElementById("divMap"));
}

function showLoadingModal()
{
    // Verify if the map loading modal is visible. If so, exit this proceedure.
    if (document.getElementById("divLoadingMapModal"))
        return;

    // Show the map loading modal progress bar.
    document.getElementById("divLoading").style.display = "";

    var objDivLoadingModal = document.createElement("div");

    addClassName(objDivLoadingModal,  "modal displayOnly");

    objDivLoadingModal.id = "divLoadingMapModal";
    objDivLoadingModal.name = "divLoadingMapModal";
    objDivLoadingModal.style.width = document.getElementById("divMap").clientWidth + 1 + "px";
    objDivLoadingModal.style.height = document.getElementById("divMap").clientHeight + 1 + "px";
    objDivLoadingModal.style.zIndex = "1";
    objDivLoadingModal.style.position = "absolute";

    // Add the div to the document object.
    document.body.appendChild(objDivLoadingModal);

    centerObjectWithin(objDivLoadingModal, document.getElementById("divMap"));
}

function doMapEvent(event)
{
    if (event != undefined)
    {
        // Update the map.
        if (event.type.toUpperCase() == "ZOOMEND")
            doMapZoomEnd();
        else if (event.type.toUpperCase() == "MOVESTART")
            doMapMoveStart();
        else if (event.type.toUpperCase() == "MOVEEND")
            doMapMoveEnd();
        else if (event.type.toUpperCase() == "MOUSEMOVE")
            doMouseMove(event);

        if ((!boolInitializingMap) && (!boolChangeMap) && (!boolMapResize) && (event.type.toUpperCase() != "MOUSEMOVE"))
        {
            // Get the navigation history control from the map.
            var objNav = objMap.getControlsByClass("OpenLayers.Control.NavigationHistory")[0];
            var divPrev = document.getElementById("divToolbarNavHistoryPrev");
            var divNext = document.getElementById("divToolbarNavHistoryNext");

            // Enable/disable the history navigation buttons.
            refreshNavHistoryButtons(divPrev, objNav, "prev");
            refreshNavHistoryButtons(divNext, objNav, "next");
        }

        objMap.getControlsByClass("OpenLayers.Control.PanZoomBar")[0].div.style.cursor = "pointer";
    }
}

function doMouseMove(event)
{
    var objBounds = new OpenLayers.Bounds();

    // Get the maximum extent of the map.
    objBounds.extend(objMap.getMaxExtent());

    var objTempLatLon = objMap.getLonLatFromViewPortPx(new OpenLayers.Pixel(event.xy.x , event.xy.y))
    if ((objTempLatLon != null) && (objTempLatLon != undefined))
    {
        var objLonLat = objTempLatLon.wrapDateLine(objBounds);

        // Display the lat/lon.
        document.getElementById("divMapCoords").innerHTML = objLonLat.lon.toFixed(3) + ", " + objLonLat.lat.toFixed(3);
    }
}

function doMapMoveEnd()
{
    if ((boolInitializingMap) || (boolChangeMap))
        return;

    // Perform dateline wrapping when in the 4326 projection.
    if (objMap.getProjection().toUpperCase() == "EPSG:4326")
        validateDateLine();
    else
        boolDateLineWrapping = false;
}

function doMapMoveStart()
{
    if ((!boolInitializingMap) && (!boolChangeMap) && (!boolPerformHistoryNav))
    {
        trackHistory("prev");

        if (getNextStack().length > 0)
        {
            // Get the navigation history control from the map.
            var objNav = objMap.getControlsByClass("OpenLayers.Control.NavigationHistory")[0];
            var divNext = document.getElementById("divToolbarNavHistoryNext");

            clearNextStack();
            refreshNavHistoryButtons(divNext, objNav, "next");
        }
    }
}

function doMapZoomEnd()
{
    if ((!boolInitializingMap)  && (!boolChangeMap))
    {
        // Hide the arrow that points the user to click on the refresh button.
        if (document.getElementById("divArrow").style.display == "")
            document.getElementById("divArrow").style.display = "none";

        // Get the layers that are hidden and refresh the map.
        refreshMap(numMapID, getHiddenLayers().join(","), true);
    }
}

function validateDateLine()
{
    if (objMap.getExtent() && ((objMap.getExtent().left < objMap.getMaxExtent().left) || (objMap.getExtent().right > objMap.getMaxExtent().right)))
    {
        // Verify if the boolDateLineWrapping is false. If so the flag needs to be changed.
        // Otherwise the map is already date line wrapping.
        if (!boolDateLineWrapping)
        {
            boolDateLineWrapping = true;

            // Get the name of the map.
            var strMapName = objMap.layers[0].name;

            // Delete the WMS layer.
            objMap.layers[0].destroy();

            // Perform a WMS request and add the layer(s) to the map.
            objMap.addLayers([doWMS(strMapName, getIncludedLayers().join(","), "")]);
        }
    }
    else
    {
        // Verify if the boolDateLineWrapping is true. If so the flag needs to be changed.
        // Otherwise the map is already not date line wrapping.
        if (boolDateLineWrapping)
        {
            boolDateLineWrapping = false;

            // Get the name of the map.
            var strMapName = objMap.layers[0].name;

            // Delete the WMS layer.
            objMap.layers[0].destroy();

            // Perform a WMS request and add the layer(s) to the map.
            objMap.addLayers([doWMS(strMapName, getIncludedLayers().join(","), "")]);
        }
    }
}

function doSetCenterZoom(pNumLon, pNumLat, pNumZoom)
{
    objMap.setCenter(new OpenLayers.LonLat(pNumLon, pNumLat), pNumZoom);
}

function doSetCenter(pNumLon, pNumLat, pNumScale)
{
    objMap.setCenter(new OpenLayers.LonLat(pNumLon, pNumLat));

    if (pNumScale != null)
    {
        objMap.zoomToScale(pNumScale);

        // Since the "zoomToScale" triggers another map "move" operation, we need to remove this zoom from the history stack.
        arryPrevStack.pop();
    }
}

function changeMap(pNumMapID)
{
    boolChangeMap = true;
    boolInitializingMap = true;

    // If the current map is the one being selected, do nothing.
    if (pNumMapID == numMapID)
    {
        boolInitializingMap = false;
        boolChangeMap = false;
        return;
    }

    logMsg("Changing map ID: " + numMapID + " to " + pNumMapID, "info", "openLayersMap.js (changeMap)");

    // Store the new map ID.
    numMapID = pNumMapID

    // Update the sidebar.
    showLegend(document.getElementById("divLegend"), pNumMapID, objMap.getScale());
    showReportableLayers(document.getElementById("divReport"), pNumMapID, objMap.getScale());
    showFilterableLayers(document.getElementById("divFilters"), pNumMapID, objMap.getScale());

    // Get the map info.
    var objResponse = getMap(pNumMapID);
    if ((objResponse != null) && (objResponse != undefined))
    {
        // Display the map info and return an array with the map title and map layers.
        var arryResult = processMap(objResponse);

        // Perform a WMS request and add the layer(s) to the map.
        doWMS(arryResult[0], getIncludedLayers().join(","), "");
    }
    else
    {
        // Exit the operation if no map info is returned.
        boolInitializingMap = false;
        boolChangeMap = false;

        return;
    }

    // Set the status of the "Select All" check box of the legend.
    initializeSelectAllStatus()

    // Clear the history stacks.
    clearPreviousStack();
    clearNextStack();

    // Get the navigation history control from the map.
    var objNav = objMap.getControlsByClass("OpenLayers.Control.NavigationHistory")[0];
    var divPrev = document.getElementById("divToolbarNavHistoryPrev");
    var divNext = document.getElementById("divToolbarNavHistoryNext");

    // Enable/disable the history navigation buttons.
    refreshNavHistoryButtons(divPrev, objNav, "prev");
    refreshNavHistoryButtons(divNext, objNav, "next");

    // Clear the variable that tracks unchecked layers.
    strUncheckedLayers = "";

    // Track the default unchecked layers.
    getExcludedLayers().join(",");

    // Default the map operation to zoom extent.
    doControlGroup(document.getElementById("ahrefZoomExtent").childNodes[0], "zoomextent");

    boolInitializingMap = false;
    boolChangeMap = false;
}

function refreshMap(pNumMapID, pStrExcludedLayers, pBoolRefreshLegendCheckboxes)
{
    // If no map ID is provided then the refresh is initiated from the legend.
    // Since the map has been loaded once, we do not need to reload it again.
    // Just process the selected layers and make a new WMS request.
    if (pNumMapID != null)
    {
        // Get the root object of the map XML info.
        var objXMLMapRoot = getMapDataXML(pNumMapID, objMap.getScale(), pStrExcludedLayers);

        // If no map record is found, display a message and exit the procedure.
        if (objXMLMapRoot.getElementsByTagName("result_count")[0].childNodes[0].nodeValue == 0)
        {
            alert(strMsgNoMapFound);
            return;
        }

        // Get the visible layers.
        var strLayersVisible = "";
        if (objXMLMapRoot.getElementsByTagName("layers_visible")[0].childNodes[0] != undefined)
            strLayersVisible = objXMLMapRoot.getElementsByTagName("layers_visible")[0].childNodes[0].nodeValue;
        else
            strLayersVisible = "";

        // Get the non-visible layers.
        var strLayersHidden = "";
        if (objXMLMapRoot.getElementsByTagName("layers_hidden")[0].childNodes[0] != undefined)
            strLayersHidden = objXMLMapRoot.getElementsByTagName("layers_hidden")[0].childNodes[0].nodeValue;
        else
            strLayersHidden = "";

        // Get the non-visible layers.
        var strLayersDisabled = "";
        if (objXMLMapRoot.getElementsByTagName("layers_disabled")[0].childNodes[0] != undefined)
            strLayersDisabled = objXMLMapRoot.getElementsByTagName("layers_disabled")[0].childNodes[0].nodeValue;
        else
            strLayersDisabled = "";

        // Update the legend (and associated slider menus) if specified.
        if (pBoolRefreshLegendCheckboxes)
        {
            updateLegend(strLayersVisible, strLayersDisabled);
            updateReport(strLayersVisible, strLayersDisabled);
            updateFilters(strLayersVisible, strLayersDisabled);
        }
    }
    else
        strLayersVisible = getIncludedLayers().join(",").trim();

    // Add the filters to the WMS request.
    var strFilters = getFilters();

    // Add the Mapit layer if it is selected.
    if (isMapitSelected())
    {
        if (strFilters.trim().length > 0)
            strFilters += "|";

        // Update the filter parameter.
        strFilters += getMapitfilter();

        // Update the layers to show.
        strLayersVisible += "," + strMapitLayerName;
    }

    if (boolGetFeatureInfo)
    {
        hideQueryRadioButtons();
        showQueryRadioButtons();
    }

    // Make a WMS call.
    doWMS(null, strLayersVisible, strFilters);
}

function toggleMeasureControl(pStrKey)
{
    // Loop through the measure controls.
    for (strKey in arryMeasureControls)
    {
        var objControl = arryMeasureControls[strKey];
        if (pStrKey.toUpperCase() == strKey.toUpperCase())
            objControl.activate();
        else
            objControl.deactivate();
    }
}

function handleMeasurementsComplete()
{
    // Remove the div at a specific time.
    if (document.getElementById("divMeasurePopUp"))
        setTimeout("removePopUp('divMeasurePopUp')", 6000);
}

function handleMeasurements(pObjEvent)
{
    var numMeasure = pObjEvent.measure;
    var strUnits = pObjEvent.units;
    var numOrder = pObjEvent.order;
    var strOutput = numMeasure.toFixed(3) + " " + strUnits;

    // Add a superscript number for area measurement.
    if (numOrder != 1)
        strOutput += "<sup>2<\/sup>";

    strOutput = "<table cellpadding='0' cellspacing='0' border='0'><tr><td>" + strOutput + "<\/td><\/tr><\/table>";

    // Display the measurement.
    var objDivMeasurePopUp = null;
    if (document.getElementById("divMeasurePopUp"))
        objDivMeasurePopUp = updateDivPopUpContent(strOutput, "divMeasurePopUp")
    else
        objDivMeasurePopUp = createDivPopUp(null, strOutput, "divMeasurePopUp", "popUpMeasure", false, false);

    // Position the div within the screen based on mouse location.
    positionObject(objDivMeasurePopUp, xMousePos + 10, yMousePos + 10);

    clearTimeout(tmrTimer);

    // Remove the div at a specific time..
    if (document.getElementById("divMeasurePopUp"))
        tmrTimer = setTimeout("removePopUp('divMeasurePopUp')", 4000);
}

function resizeMap(pStrAction)
{
    var objDivMap = document.getElementById("divMapContent");

    if (pStrAction.toUpperCase() == "HIDESIDEBAR")
        objDivMap.className = objDivMap.className.replace(/defaultMapWidth/ig, "resizeMapWidth").trim();
    else
        objDivMap.className = objDivMap.className.replace(/resizeMapWidth/ig, "defaultMapWidth").trim();

    // Openlayers does not refresh the map automatically in Firefox so we need to force a refresh.
    if (navigator.appName != "Microsoft Internet Explorer")
    {
        // Set the boolMapResize flag as to not create a navigation
        // history when repositioning the center of the map.
        boolMapResize = true;

        // Reposition the center of the map when the map is resized.
        doSetCenter(objMap.getCenter().lon, objMap.getCenter().lat, null)

        boolMapResize = false;
    }
}
