
var agiExtents = new Extents();


// Map submission functions

var OVERVIEW_ZOOM = 2.5;

var lastRequest_ = 0;

function requestMap() {
    clearTimeout( lastRequest_ );
    lastRequest_ = setTimeout( refreshMap, 80 );
}

function refreshMap() {
    submitMainMap( "" );
    submitOverview();
    lastRequest_ = 0;
}

function submitMainMap() {
    agiExtents.persistExtent();
    updateZoomLevel( agiMapViewer.getLevel() );
    showWaitImage();

    mapParams = agiMapViewer.getViewParams() + getTaskParams( agiSubmitter ) + bufferDrawParams;
    if (zoomToBuffer)
    {
        mapParams += "&zoomToBuffer=true";
        zoomToBuffer = false;
    }
    submitMainMap.params = mapParams
    createMap( mapParams, true, mapCallback );
}

function submitOverview() {
    m_overviewViewer.setExtent( agiMapViewer.getExtent() )
    m_overviewViewer.zoom( OVERVIEW_ZOOM )

    mapParams = m_overviewViewer.getViewParams() + overviewLayersParam();
    createMap( mapParams, false, overviewCallback );
}

function createMap( params, forMainMap, callback) {
    eval( mapMaker.value + ".createMap( params, forMainMap, callback );" );
}

function mapCallback( returnObj ) {
    m_imgMapCanvas.src = returnObj.value;
}

function overviewCallback( returnObj ) {
    m_imgOverviewCanvas.src = returnObj.value;
}

function getTaskParams( submitter ) {
    var params="";
    for ( var i=0; i < submitter.length; i++) {
       params += submitter[i]();
    }
    return params;
}

function updateZoomLevel( inLevel ) {
    var nLevels = m_ExtentWidths.length;
    for (i=1 ; i<nLevels+1 ; i++) {
        document.getElementById('imgZoomLevel' + i).src = 'AGIMapControls/images/tick.gif';
        if (i == inLevel) {
            document.getElementById('imgZoomLevel' + i).src = 'AGIMapControls/images/tick_selected.gif';
        }
    }
}


// Highlight Methods

function highlightFeature( layerID, featureID ) {
    highlightLayerId.value   = layerID.toString();
    highlightFeatureId.value = featureID.toString();
    requestMap();
}

function highlightFeatureUrl() {
    // Add &-url-params to highlight feature associated with highLightValue.
    if (highlightLayerId.value.length > 0 && highlightFeatureId.value.length > 0)
        return "&highLightLayer=" + highlightLayerId.value +
               "&highLightValue=" + highlightFeatureId.value;
    return "";
}


// Map function/class

function map( left, top, width, height, widths, extent, showScale ) {
    var m_rectExtent;     // Extent of the map in map units
    var m_queryExtent;    // Extent of the map in map units
    var m_iCurrentLevel;  // Current level of the map.

    var m_iTagLeft   = parseInt( left );    // These are dimensions, in
    var m_iTagTop    = parseInt( top );     //   page units, which describe
    var m_iTagWidth  = parseInt( width );   //   the position of the image
    var m_iTagHeight = parseInt( height );  //   tag representing the map.

    var m_arrWidths  = widths;    // Array of levels widths to associate with the map as an alternate means of zooming in or out.
    var m_showScale  = showScale; // Whether to add a scale bar

    setExtent( extent );

    this.setExtent      = setExtent;
    this.getExtent      = getExtent;
    this.setQueryExtent = setQueryExtent;
    this.getQueryExtent = getQueryExtent;
    this.setLevel       = setLevel;
    this.getLevel       = getLevel;

    this.getViewParams   = getViewParams;
    this.getExtentParams = getExtentParams;
    this.isEventOverMap  = isEventOverMap;
    this.toMapPoint      = toMapPoint;
    this.toPagePoint     = toPagePoint;
    this.recenter        = recenter;
    this.zoom            = zoom;
    this.moveEast        = moveEast;
    this.moveNorth       = moveNorth;
    this.moveSouth       = moveSouth;
    this.moveWest        = moveWest;


    // ------------------
    // Map Extent methods
    // ------------------

    function getExtent()      { return m_rectExtent; } 
    function getQueryExtent() { return m_queryExtent; } 
    function getLevel()       { return m_iCurrentLevel; }

    function setExtent( rectExtent ) {
        m_rectExtent    = getAspectAdjustedRect( rectExtent, m_iTagWidth, m_iTagHeight );
        m_iCurrentLevel = findLevel( m_rectExtent );
        setQueryExtent( m_rectExtent );
        agiZoomBox.hide();
    }

    function setQueryExtent( rectExtent ) {
        m_queryExtent = rectExtent;
    }

    function setLevel( level ) {
        setExtent( buildLevelRect( level ) );
    }

    function move( eastFactor, northFactor ) {
        var x = m_rectExtent.getCenter().x + (m_rectExtent.getWidth()  * eastFactor);
        var y = m_rectExtent.getCenter().y + (m_rectExtent.getHeight() * northFactor);
        recenter( new point( x, y ));
    }

    function moveEast()  { move(  0.5,  0.0 ); } 
    function moveNorth() { move(  0.0,  0.5 ); } 
    function moveSouth() { move(  0.0, -0.5 ); } 
    function moveWest()  { move( -0.5,  0.0 ); } 

    function recenter( ptNewCenter ) {
        setExtent(
            new rect (
                ptNewCenter.x - (m_rectExtent.getWidth()  / 2),
                ptNewCenter.y - (m_rectExtent.getHeight() / 2),
                ptNewCenter.x + (m_rectExtent.getWidth()  / 2),
                ptNewCenter.y + (m_rectExtent.getHeight() / 2)
            )
        );
    }

    function zoom( scale ) {
        m_rectExtent.scale( scale );
        m_iCurrentLevel = findLevel( m_rectExtent );
    }


    // -------------------------------
    // Map/Page Transformation methods
    // -------------------------------

    function getViewParams() {
        return getExtentParams() +
               "&WIDTH="     + m_iTagWidth  +
               "&HEIGHT="    + m_iTagHeight +
               "&showScale=" + m_showScale;
    }

    function getExtentParams() {
        return "XMIN="  + getExtent().getLeft()   +
               "&YMIN=" + getExtent().getBottom() +
               "&XMAX=" + getExtent().getRight()  +
               "&YMAX=" + getExtent().getTop();
    }

    function isEventOverMap( eventX, eventY ) {
        var offsetWidth  = document.body.offsetWidth;
        var clientWidth  = document.body.clientWidth;
        var offsetHeight = document.body.offsetHeight;
        var clientHeight = document.body.clientHeight;

        if ((eventX > clientWidth)                 ||
            (eventY > clientHeight)                ||
            (eventX <= m_iTagLeft)                 ||
            (eventY <= m_iTagTop)                  ||
            (eventX > (m_iTagWidth  + m_iTagLeft)) ||
            (eventY > (m_iTagHeight + m_iTagTop))) {
            return false;
        }
        return true;
    }

    function toMapPoint( pageX, pageY ) {
        var ratioW =                 (pageX - m_iTagLeft) / m_iTagWidth;
        var ratioH = (m_iTagHeight - (pageY - m_iTagTop)) / m_iTagHeight;
        var mapX   = m_rectExtent.getLeft()   + ratioW * m_rectExtent.getWidth();
        var mapY   = m_rectExtent.getBottom() + ratioH * m_rectExtent.getHeight();
        return new point( mapX, mapY );
    }

    function toPagePoint( mapX, mapY ) {
        var iX = (mapX - m_rectExtent.getLeft()  ) * m_iTagWidth  / m_rectExtent.getWidth();
        var iY = (mapY - m_rectExtent.getBottom()) * m_iTagHeight / m_rectExtent.getHeight();
        return new point( m_iTagLeft + iX, m_iTagTop + m_iTagHeight - iY );
    }


    // -----------------
    // Private Functions
    // -----------------

    function buildLevelRect( level ) {
        var dblWidth = m_arrWidths[level - 1];
        return new rect(
            m_rectExtent.getCenter().x - (dblWidth / 2),
            m_rectExtent.getCenter().y,
            m_rectExtent.getCenter().x + (dblWidth / 2),
            m_rectExtent.getCenter().y
        );
    }

  function findLevel( rectExtent ) {
        var numLevels = m_arrWidths.length;

        for (i=0;i<numLevels;i++) {
            if (m_arrWidths[i] + .001 >= rectExtent.getWidth())
                return i + 1;
        }
        return numLevels;
    }

    function getAspectAdjustedRect( rectExtent, iWidthPixels, iHeightPixels ) {
        // Adjust the width or height of the rectangle so its aspect ratio matches that of the given dimensions
        var dblExtentRatio = rectExtent.getHeight() / rectExtent.getWidth();
        var dblMapRatio    = iHeightPixels          / iWidthPixels;

        if (dblExtentRatio > dblMapRatio)
            return makeRectFromCenter( rectExtent.getCenter(), rectExtent.getHeight() / dblMapRatio, rectExtent.getHeight() );
        else
            return makeRectFromCenter( rectExtent.getCenter(), rectExtent.getWidth(),                rectExtent.getWidth() * dblMapRatio );
    }

    function makeRectFromCenter( ptCenter, dblWidth, dblHeight ) {
        var dblLeft   = ptCenter.x - (dblWidth  / 2);
        var dblRight  = ptCenter.x + (dblWidth  / 2);
        var dblBottom = ptCenter.y - (dblHeight / 2);
        var dblTop    = ptCenter.y + (dblHeight / 2);
        return new rect( dblLeft, dblBottom, dblRight, dblTop );
    }
}

