/*********************************************************************************
 Copyright (c) 2002-2003 Armin Burger
 
 Permission is hereby granted, free of charge, to any person obtaining 
 a copy of this software and associated documentation files (the "Software"), 
 to deal in the Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 and/or sell copies of the Software, and to permit persons to whom the Software 
 is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included 
 in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR 
 COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************************/

// ================== FUNCTIONS FOR ZOOM AND PAN  =====================//
// will only work with modern browsers, NOT with 4.x versions          //
// Successfully tested with Mozilla 1.0+, Firefox, IE 5.5+, Opera 6, Konqueror 3//

  
/*
 * GLOBAL VARIABLES
 ******************************************************/
var mouseDrag = false;    // TRUE when mouse is pressed
var maction;

var downX, downY;
var upX, upY;
var moveX, moveY;

var offsX = 0; 		// horizontal image offset
var offsY = 0;      // vertical image offset

var rBoxMinW = 8;  // Minimal width until to show refBox; below threshold switches to refCross
var rOffs = 13;     // Offset of refCross Image, adapt to Image size and refbox border

if (document.all) {
    var zBorder = 0;
} else {
    var zBorder = 4;
}

var refmapClick = false;
var mapcL, mapcT, mapcL, mapcR;
var mapElem; 


/*
 * DEFINE MOUSE ACTIONS, CALLED AS 'ONLOAD' SCRIPT
 ******************************************************/
// FOR MOUSE OVER MAP
function startUp() {
    refmapClick = false;
    mapElem = document.getElementById('map');
    if (mapElem) {
        mapElem.onmousedown = doMouseDown; 
        mapElem.onmouseup   = doMouseUp;
        mapElem.onmousemove = doMouseMove;   
        
        // ENABLES ACTIONS FOR KEYBOARD KEYS
        // comment out if not wanted
        if (document.all) document.onkeydown = kp;
        document.onkeypress = kp; 
        
        setCursorMinMax('map');
    }
}


// FOR MOUSE OVER REFERENCE MAP
function startUpRef() {
    refmapClick = true;
    refElem = document.getElementById('refmap');
    if (refElem) {
        refElem.onmousedown = doMouseDown; 
        refElem.onmouseup   = doMouseUp;
        refElem.onmousemove = doMouseMove;   
    
        setCursorMinMax('refmap');
    }
}


// MIN AND MAX VALUES FOR MOUSE
function setCursorMinMax(elem) {
    // MAP
    if (elem == 'map') {
        mapcL = parseInt(document.getElementById('mapFrame').style.left) 
                + parseInt(document.getElementById('map').style.left);
        mapcT = parseInt(document.getElementById('mapFrame').style.top) 
                + parseInt(document.getElementById('map').style.top);
        mapcR = mapcL + mapW;
        mapcB = mapcT + mapH;
    // REFERENCE MAP
    } else {
        mapcL = parseInt(document.getElementById('refmap').style.left);
        mapcT = parseInt(document.getElementById('refmap').style.top);
        mapcR = mapcL + refW;
        mapcB = mapcT + refH;
    }
    
    offsX = mapcL; 		// horizontal image offset
    offsY = mapcT; 
}


function checkCursorPosition(cX, cY) {
    if (cX >= mapcL && cX <= mapcR && cY >= mapcT && cY <= mapcB) {
        return true;
    } else {
        return false;
    }
}



/*
 * FUNCTIONS TO GET MOUSE POSITIONS
 ******************************************************/
// For MouseDown
function getDownXY(e) {
    if (document.all) {
		eX = event.clientX;
        eY = event.clientY;
	} else {
		eX = e.pageX;
		eY = e.pageY;
	}
	// subtract offsets
        
    downX = eX - offsX;
    downY = eY - offsY;
    
    mapElem.onmouseup   = doMouseUp;
    mapElem.onmousemove = doMouseMove;
    mapElem.ondblclick  = doMouseDblClick;  // used for measure area, comment out if area measurement not wanted

    //alert (downX + ' - ' + downY);

    return false;	
}


// For MouseUp
function getUpXY(e) {
    if (document.all) {
        eX = event.clientX;
        eY = event.clientY;
    } else {
        eX = e.pageX;
        eY = e.pageY;
    }
    // subtract offsets from left and top and don't go outside of map
    
    if (!refmapClick) {
        upX = Math.min(eX - offsX, mapW);
        upY = Math.min(eY - offsY, mapH);
    } else {
        upX = eX - offsX;
        upY = eY - offsY;
    }

    return false;

}


// For MouseMove
function getMoveXY(e) {
    if (document.all) {
        moveX = event.clientX;
        moveY = event.clientY;
    } else {
        moveX = e.pageX;
        moveY = e.pageY;
    }
    // subtract offsets from left and top
    /*moveX = Math.min(moveX - offsX, mapW);
    moveY = Math.min(moveY - offsY, mapH); */
    moveX = moveX - offsX;
    moveY = moveY - offsY;             
}


/*
 * BASIC MOUSE FUNCTIONS: DOWN, UP, MOVE
 ******************************************************/

function doMouseDown(e) {

    // ENABLES ACTIONS FOR KEYBOARD KEYS
    // comment out if not wanted
    if (document.all) document.onkeydown = kp;
    document.onkeypress = kp;
    
    mouseDrag = true;
    getDownXY(e);
    
    if (refmapClick) {
        if (downX < 1 || downY < 1 || downX > refW || downY > refH) {        // Don't go ouside of map
            return false;
        } else {
            moveRefBox('shift');
        }
    }
    
    return false;
}


function doMouseUp(e) {
    mouseDrag = false;
    getUpXY(e);
    
    //alert(upX + ' - ' + upY + ' - ' + maction);
    // Click in main map
    if (!refmapClick) {
        maction = document.varform.maction.value;
        if (maction == 'measure') {
            measureDrawSymbols(e, upX, upY, 0);

        } else if (maction == 'pan'){
            var diffX = upX - downX;
            var diffY = upY - downY;
            // pan with click
            if (diffX == 0 && diffY == 0) {
                var newX = upX;
                var newY = upY;
            // pan with drag
            } else {
                var newX = (mapW / 2) - diffX ;
                var newY = (mapH / 2) - diffY;
            }
            //alert(newX +', '+ newY +', '+ newX +', '+ newY);
            zoombox_apply(newX, newY, newX, newY);
        
        } else if (maction == 'click'){
            zoombox_apply(downX, downY, downX, downY);    

        } else {
            zoombox_apply(Math.min(downX,upX), Math.min(downY,upY), Math.max(downX,upX), Math.max(downY,upY));
        }

    // Click in reference map
    } else {
        if (upX < 1 || upY < 1 || upX > refW || upY > refH) {   // Don't go ouside of map
            return false;
        } else {
            //alert(upX +', '+ upY +', '+ upX +', '+ upY);
            zoombox_apply(upX, upY, upX, upY);
        }
    }
    
    
    return false;    
}


function doMouseMove(e) {
    getMoveXY(e);
    /* * Draw a zoombox when mouse is pressed and zoom-in or select function are active
       * move map layer when pan function is active
       * do nothing for all others                                                      */

    // Actions in MAIN MAP
    if (!refmapClick) {
        if (document.varform) {
            maction = document.varform.maction.value;
        }
        
        // Display coordinates of current cursor position
        displayCoordinates();        
        	
        
        switch (maction) {
            //# zoom-in, select
            case 'box':
                startZoomBox(e, moveX, moveY);
                break;
    
            //# zoom-out, identify
            case 'click':
                hideLayer('zoombox');
                break;
    
            //# pan with drag
            case 'pan':
                hideLayer('zoombox');
                startPan(e, moveX, moveY);
                break;
    
            //# measure
            case 'measure':
                showLayer('measure')
                break;
        }
    // Actions in REFERENCE MAP
    } else {
        hideLayer('zoombox');
        if (mouseDrag) {
            moveRefBox('move');
        }
    }
    
    return false;    
}


// For DOUBLE CLICK 
// currently only used for measure function: end measure, calculate polygon area
function doMouseDblClick(e) {
    getUpXY(e);
    maction = document.varform.maction.value;
    if (maction == 'measure') {
        measureDrawSymbols(e, upX, upY, 1);
    }
}  




/*
 * FUNCTIONS FOR ZOOM BOX && PAN MOVING MAP
 ******************************************************/

// DRAG ZOOM BOX (ZOOM IN, SELECT)
function startZoomBox(e, moveX, moveY) {
    if (mouseDrag == true) {
        if (checkCursorPosition(moveX + offsX, moveY + offsY)) {
            showLayer('zoombox');
            var boxL = Math.min(moveX, downX);
            var boxT = Math.min(moveY, downY);
            var boxW = Math.abs(moveX - downX);
            var boxH = Math.abs(moveY - downY);

            var theZoomBox = document.getElementById("zoombox");
            theZoomBox.style.left   = boxL;
            theZoomBox.style.top    = boxT;
            theZoomBox.style.width  = boxW;
            theZoomBox.style.height = boxH;
        }
    }
    return false;
}

// PAN
function startPan(e, moveX, moveY) {
    if (mouseDrag == true) {
        
        if (checkCursorPosition(moveX + offsX, moveY + offsY)) {
            var mapL = moveX - downX;
            var mapT = moveY - downY;
    
            var theMapImg = document.getElementById("mapimg");
            var theMapImgL = document.getElementById("mapimgLayer");
            
            var clipT = 0;
            var clipR = mapW;
            var clipB = mapH;
            var clipL = 0;
            
            theMapImgL.style.top  = mapT;
            theMapImgL.style.left = mapL;
            
            if (mapT > 0) {
                clipB = mapH - parseInt(theMapImgL.style.top);
            } else {
                clipT = -1 * parseInt(theMapImgL.style.top);     
            }
            
            if (mapL > 0) {
                clipR = mapW - parseInt(theMapImgL.style.left);
            } else {
                clipL = -1 * parseInt(theMapImgL.style.left);
            }
            
    
            var clipRect = 'rect(' + clipT + 'px ' 
                                   + clipR + 'px '
                                   + clipB + 'px ' 
                                   + clipL + 'px)'; 
            //window.status = clipRect;
            theMapImgL.style.clip = clipRect;

        }
    }
    return false;
}


/*
 * FUNCTIONS FOR REFERENCE MAP RECTANGLE
 ******************************************************/
function setRefBox(boxL, boxT, boxW, boxH) {
    //showLayer('refbox');
    var rBox = window.parent.document.getElementById("refbox");
    var sBox = window.parent.document.getElementById("sliderbox");
    var rCross = window.parent.document.getElementById("refcross");
    
    if (rBox) {
        rBox.style.left   = boxL;
        rBox.style.top    = boxT;
        rBox.style.width  = boxW; //Math.max(4, boxW);
        rBox.style.height = boxH; //Math.max(4, boxH);
    }
    
    if (rCross) {
        if (boxW < rBoxMinW) {
            rBox.style.visibility = "hidden";
            rCross.style.visibility = "visible";
            setRefCross(rCross, boxL, boxT, boxW, boxH);
        } else {
            rCross.style.visibility = "hidden";
            rBox.style.visibility = "visible";
        }
    }
    
    if (sBox) {
        sBox.style.visibility = "hidden";
    }
}

// MOVE RECTANGLE WITH MOUSE PAN
function moveRefBox(moveAction) {
    var rBox = document.getElementById("refbox");
    var rCross = document.getElementById("refcross");

    var boxL = parseInt(rBox.style.left);
    var boxT = parseInt(rBox.style.top);
    var boxW = parseInt(rBox.style.width);
    var boxH = parseInt(rBox.style.height);
    
    if (moveAction == 'shift') {
        var newX = downX; 
        var newY = downY;        
    } else {
        var newX = moveX; 
        var newY = moveY; 
    }
    
    boxLnew = newX - (boxW / 2) - 1; 
    boxTnew = newY - (boxH / 2) - 1;
    
    if (boxLnew < 0 || boxTnew < 0 || (boxLnew + boxW) > refW || (boxTnew + boxH) > refH) {
        return false;
    } else {
        rBox.style.left = boxLnew;
        rBox.style.top  = boxTnew;
        window.status = (boxLnew + boxW + ' - ' + refW);
        
        if (boxW < rBoxMinW) {
            setRefCross(rCross, boxLnew, boxTnew, boxW, boxH);
        }
    }
}


// Change position of reference cross
// => symbol used when refbox below threshold
function setRefCross(rCross, boxL, boxT, boxW, boxH) {
    boxcX = boxL + (boxW / 2);
    boxcY = boxT + (boxH / 2);
    rCross.style.left = Math.round((boxcX - rOffs));
    rCross.style.top  = Math.round((boxcY - rOffs));
}



// SET DIV LAYER VISIBLE - HIDDEN
function showLayer(elementID) {
    var theZoomBox = document.getElementById(elementID);
    theZoomBox.style.visibility = "visible";
}

function hideLayer(elementID) {
    var theZoomBox = document.getElementById(elementID);
    theZoomBox.style.visibility = "hidden";
}



/*******************************************************************
 * Resize map image while zooming with slider
 * called from sliderMove() in slider.js
 ********************************************/
function resizeMap(sizeFactor) {
    var theMapImg = document.getElementById('mapImg');
    var theMapLay = document.getElementById('mapimgLayer');
    
    var oldW = mapW;
    var oldH = mapH;
    var newW = oldW * sizeFactor;
    var newH = oldH * sizeFactor;
    
    var newLeft = (oldW - newW) / 2;
    var newTop  = (oldH - newH) / 2;

    theMapImg.style.width   = newW;
    theMapImg.style.height  = newH;
    theMapLay.style.left = newLeft; 
    theMapLay.style.top  = newTop;
    
    if (sizeFactor > 1) {
        var diffW = parseInt((newW - oldW) / 2);
        var diffH = parseInt((newH - oldH) / 2);
        clipT = diffH;
        clipR = diffW + oldW;
        clipB = diffH + oldH;
        clipL = diffW;

        var clipRect = 'rect(' + clipT + 'px ' 
                               + clipR + 'px '
                               + clipB + 'px ' 
                               + clipL + 'px)'; 
        //window.status = clipRect;
        theMapLay.style.clip = clipRect;
        
        theMapLay.style.width   = newW;
        theMapLay.style.height  = newH;
    } 
}


function resizeRefBox(sizeFactor) { 
    var refZoomBox = document.getElementById('refbox');
    var refSliderBox = document.getElementById('refsliderbox');
    
    if (refSliderBox) {
        refSliderBox.style.visibility = "visible";
    }
    
    if (refZoomBox) {
        var refBoxBorderW = 1;  // adapt to border width in CSS

        var oldRefW = parseInt(refZoomBox.style.width);
        var oldRefH = parseInt(refZoomBox.style.height);
        var oldRefLeft = parseInt(refZoomBox.style.left);
        var oldRefTop = parseInt(refZoomBox.style.top);
        
        var newRefW = Math.round(oldRefW / sizeFactor);
        var newRefH = Math.round(oldRefH / sizeFactor);
        
        var newRefLeft = parseInt(oldRefLeft + ((oldRefW - newRefW) / 2) + refBoxBorderW);
        var newRefTop  = parseInt(oldRefTop + ((oldRefH - newRefH) / 2) + refBoxBorderW);
        
        refSliderBox.style.left   = newRefLeft;
        refSliderBox.style.top    = newRefTop;
        refSliderBox.style.width  = newRefW;
        refSliderBox.style.height = newRefH;
    }
}




/*
 * KEYBOARD FUNCTIONS
 * original script taken from http://ka-map.maptools.org/
 ******************************************************************/
function kp(e) {
    e = (e)?e:((event)?event:null);
    if(e) {
        var charCode=(e.charCode)?e.charCode:e.keyCode;
        //alert(charCode);
        //var charCode=(e.charCode != 0) ? e.charCode : e.keyCode;
        var b=true;
        var nStep = 16;
        switch(charCode){
          case 63232://safari up arrow
          case 38://up arrow
            arrowpan('n');
            //moveBy(0,nStep);
            break;
          case 63233://safari down arrow
          case 40://down arrow
            arrowpan('s');
            //moveBy(0,-nStep);
            break;
          case 63234://safari left arrow
          case 37:// left arrow
            arrowpan('w');
            //moveBy(nStep,0);
            break;
          case 63235://safari right arrow
          case 39://right arrow
            arrowpan('e');
            //moveBy(-nStep,0);
            break;
          case 63276://safari pageup
          case 33://pageup
            gofwd();
            break;
          case 63277://safari pagedown
          case 34://pagedown
            goback();
            break;
          case 63273://safari home (left)
          case 36://home
            zoomfullext();
            break;
          case 63275://safari end (right)
          case 35://end
            slideBy(-viewportWidth/2,0);
            break;
          case 43:
            //moveBy(20, 4);
            zoompoint(2, '');
            break;
         case 45:
            zoompoint(-2, '');
            break;
          default:
            b=false;
        }
    }
}


function moveBy(a, b) {
    alert(a + ' - ' + b); 
}
     




/* 
 * AUXILIARY FUNCTIONS
 ******************************/
// GET MAP COORDINATES FOR MOUSE MOVE
function getCoords(mouseX, mouseY) {
    var x_geo = Math.round(minx_geo + ((mouseX/mapW) * xdelta_geo));
    var y_geo = Math.round(maxy_geo - ((mouseY/mapH) * ydelta_geo));

    var mapCoords = 'X: ' + x_geo + '  Y: ' + y_geo;
    return  mapCoords;

}

// DISPLAY MAP COORDINATES FOR MOUSE MOVE
function displayCoordinates() {
    var mouseString = getCoords(moveX, moveY);
    window.status = mouseString;
}
