//-- Global Variables
var iMapWidth = 500;	//-- Image width (default)
var iMapHeight = 400;	//-- Image height (default)
var sMapCanvasID = "MapCanvas"; // ID of map overlay element tbat the drawing is done in (default)
var sMapOverlayID = "MapOverlay"; // ID of map overlay element that events are bound to (default)
var objMapCanvas;


//## Tools Available ("constants")
var TOOL_RECT = "TOOL_RECT";
var TOOL_LINE = "TOOL_LINE";
var TOOL_POLYLINE = "TOOL_POLYLINE";
var TOOL_POLYGON = "TOOL_POLYGON";
var TOOL_ZOOMIN = "TOOL_ZOOMIN";
var TOOL_ZOOMOUT = "TOOL_ZOOMOUT";
var TOOL_PAN = "TOOL_PAN";
var TOOL_IDENTIFY = "TOOL_IDENTIFY";
var TOOL_PIXEL_VALUE_1 = "TOOL_PIXEL_VALUE_1";
var TOOL_PIXEL_VALUE_2 = "TOOL_PIXEL_VALUE_2";
var TOOL_PIXEL_VALUE_3 = "TOOL_PIXEL_VALUE_3";

var TOOL_CURRENT = TOOL_ZOOMIN;


//## Storage variables
var bolIsDragging = false;

//-- For polygon and polyline tools
var arrXPoints;
var arrYPoints;

var intRectLeft = 0;
var intRectRight = 0;
var intRectTop = 0;
var intRectBottom = 0;

var intMouseX=0;
var intMouseY=0;
var intX1=0;
var intY1=0;
var intX2=0;
var intY2=0;


//## Browser Detection
var isNav = (navigator.appName.indexOf("Netscape") >= 0);
var isNav4 = false;
var isIE4 = false;
var is5up = false;

if(isNav) {
	if(parseFloat(navigator.appVersion) < 5) {
		isNav4=true;
	} else {
		is5up = true;
	}
} else {
	isIE4 = true;
	if(navigator.appVersion.indexOf("MSIE") > 0) {
		isIE4 = false;
		is5up = true;
	}
}



/*****************************************
            GENERAL FUNCTIONS
*****************************************/
/**
 * Initialise the drawing library and sets up the map canvas.
*/
function TB_initTools(MapOverlayID, MapCanvasID, LineWidth, LineColor, iWidth, iHeight) {
    iMapWidth = iWidth;
    iMapHeight = iHeight;
    sMapOverlayID = MapOverlayID;
    sMapCanvasID = MapCanvasID;

    //-- Drawing tools
    objMapCanvas = new jsGraphics(MapCanvasID);
    objMapCanvas.setStroke(LineWidth);
    objMapCanvas.setColor(LineColor);

    //-- Bind events
    var objMapOverlay = $(MapOverlayID);
    objMapOverlay.onmousedown = TB_OnMouseDown;
    objMapOverlay.onmouseup = TB_OnMouseUp;
    objMapOverlay.ondblclick = TB_OnDoubleClick;
    objMapOverlay.onmousemove = TB_OnMouseMove;

    //-- Fix for IE. Hide from Opera masquerading as IE. (not reliable)
    if(navigator.userAgent.indexOf('MSIE') != -1 && navigator.userAgent.indexOf('Opera') == -1) {
        objMapOverlay.style.backgroundColor = "#000000";
        objMapOverlay.style.filter = "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    }

    if(typeof TOOL_ZOOMIN != "undefined" || typeof TOOL_ZOOMOUT != "undefined")
        TB_updateCursor();
};

/**
 * Alter the cursor type for the map depending on the selected tool.
*/
function TB_updateCursor() {
    if(!is5up) return;

    var objMapOverlay = $(sMapOverlayID);
    if(objMapOverlay == null) return;

    switch(TB_getTool()) {
        case TOOL_ZOOMIN:
        case TOOL_ZOOMOUT:
        case TOOL_PAN:
        case TOOL_IDENTIFY:
        case TOOL_PIXEL_VALUE_1:
        case TOOL_PIXEL_VALUE_2:
        case TOOL_PIXEL_VALUE_3:
            objMapOverlay.style.cursor = "crosshair";
            break;

        default:
            objMapOverlay.style.cursor = "default";
    }
};

/**
 * Set a tool as active.
*/
function TB_setTool(ToolID) {
	TB_cancelTool();
	TOOL_CURRENT = ToolID;
};

/**
 * Retreive the currently active tool.
 * @return string - A TOOL_ "constant"
*/
function TB_getTool() {
	return TOOL_CURRENT;
};

/**
 * Register this as the last used tool so printing knows what shape to draw.
*/
function TB_setLastTool(ToolID) {
		if(typeof document.MapForm.lstmeasuring_tool != "undefined")
    	document.MapForm.lstmeasuring_tool.value = ToolID;
};

/**
 * Stop the active tool and clear any drawing done.
*/
function TB_cancelTool() {
    draw_stopDrag();
    objMapCanvas.clear();
};

/**
 * Wrapper to distinguish between measuring tools and others.
 * @return boolean
*/
function TB_isMeasuringTool(ToolID) {
    switch(ToolID) {
        case TOOL_RECT:
        case TOOL_LINE:
        case TOOL_POLYLINE:
        case TOOL_POLYGON:
            return true;

        default:
            return false;
    }
};

/**
 * Setup the conditons required for a tool to begin drawing.
*/
function draw_startDrag(x, y) {
	intX1 = x;
	intY1 = y
	intX2 = intX1 + 1;
	intY2 = intY1 + 1;
	bolIsDragging = true;
};

/*
 * Store coordinates in the global X2 and Y2 variables. Used by rectangles.
*/
function draw_updateDrag(x, y) {
	intX2 = x;
	intY2 = y;
};

/**
 * Wrapper to set bolIsDragging to false.
*/
function draw_stopDrag() {
	bolIsDragging = false;
	return true;
};

/**
 * Utility function to check that the event generated by the mouse moving is indeed over
 * the canvas and not one of the <div> elements used for the drawing.
 * @return boolean
*/
function draw_CheckCanvas(objEvent) {
    //-- IE
    if(typeof objEvent.srcElement != "undefined" && objEvent.srcElement != null) {
        if(typeof objEvent.srcElement.id == "string" && objEvent.srcElement.id == sMapOverlayID)
            return true;

    } else {
    //-- Other browsers
        if(typeof objEvent.target.id == "string" && objEvent.target.id == sMapOverlayID)
            return true;
    }
    return false;
};



/*****************************************
        WRAPPER FUNCTIONS
*****************************************/
function TB_startTool(x,y) {
    //-- Firefox 3.X fix to ensure focus doesn't get stolen when you've drawn a shape.
    document.body.focus();

    switch(TB_getTool()) {
        case TOOL_RECT:
            draw_startRect(x,y);
            break;
        case TOOL_LINE:
            draw_startLine(x,y);
            break;
        case TOOL_POLYLINE:
            draw_startPolyline(x,y);
            break;
        case TOOL_POLYGON:
            draw_startPolygon(x,y);
            break;
        case TOOL_ZOOMIN:
        case TOOL_ZOOMOUT:
    				draw_startRect(x,y);
            break;
        case TOOL_PAN:
            onClickXY(x,y);
            break;
        case TOOL_IDENTIFY:
            onClickXY(x,y);
            break;
        case TOOL_PIXEL_VALUE_1:
            onPixelValue(x, y, 0, 100);
            break;
        case TOOL_PIXEL_VALUE_2:
            onPixelValue(x, y, 0, 50);
            break;
        case TOOL_PIXEL_VALUE_3:
            onPixelValue(x, y, -100, 100);
            break;
    }
};

/**
 * Handles updating the shape as it's being drawn.
 *
 * @param x, y - the current mouse coordinates over the map.
*/
function TB_dragTool(x,y) {
    switch(TB_getTool()) {
        case TOOL_RECT:
        case TOOL_ZOOMIN:
        case TOOL_ZOOMOUT:
            draw_Rect(x,y);
            break;
        case TOOL_LINE:
            draw_Line(x,y);
            break;
        case TOOL_POLYLINE:
            draw_Polyline(x,y);
            break;
        case TOOL_POLYGON:
            draw_Polygon(x,y);
            break;
    }
};

/**
 * Handles operations when drawing finishes.
 *
 * @param x, y - the final mouse coordinates over the map.
*/
function TB_stopTool(x,y) {
    switch(TB_getTool()) {
        case TOOL_RECT:
        case TOOL_ZOOMIN:
        case TOOL_ZOOMOUT:
            draw_stopRect();
            break;
        case TOOL_LINE:
            draw_stopLine();
            break;
    }
};

function TB_stopPolyTool() {
    switch(TB_getTool()) {
        case TOOL_POLYLINE:
            draw_stopPolyline();
            break;
        case TOOL_POLYGON:
            draw_stopPolygon();
            break;
    }
};


/**
 * Wrapper for calling the function that does whatever the tool is intended to do (eg: an Ajax request, submitting a form, etc).
 *
 * @param x1, y1 - The mouse coordinates over the map which drawing started at.
 * @param x2, y2 - The mouse coordinates over the map which drawing finished at.
*/
function TB_finishTool(x1, y1, x2, y2) {
    switch(TB_getTool()) {
        case TOOL_RECT:
        	mt_RectangleTool(x1, y1, x2, y2);
        	break;

        case TOOL_ZOOMIN:
        case TOOL_ZOOMOUT:
        	if((x2 - x1) > 1) {
    				objMapCanvas.clear();
        		onZoomBox(x1, y1, x2, y2); //-- Zoom in or out w/ Box
        	} else {
        		onZoomXY(x1, y1); //-- Zoom in or out to specifified point
        	}
        	break;

				case TOOL_LINE:
        	mt_LineTool(x1, y1, x2, y2);
					break;
    }
};

function TB_finishPolyTool(arrPoints1, arrPoints2) {
    switch(TB_getTool()) {
				case TOOL_POLYLINE:
					mt_PolylineTool(arrPoints1, arrPoints2);
					break;

				case TOOL_POLYGON:
					mt_PolygonTool(arrPoints1, arrPoints2);
					break;
    }
};



/*****************************************
        SHAPE SPECIFIC FUNCTIONS
*****************************************/

/*########## RECT ######################*/
/**
 * Begin drawing a rectangle (onmousedown)
*/
function draw_startRect(x, y) {
    draw_startDrag(x, y);
    draw_updateRect();
};

/**
 * Draw a rectangle from the origin point to x, y (onmousemove)
*/
function draw_Rect(x, y) {
    objMapCanvas.clear();
    draw_updateDrag(x, y);
    draw_updateRect();

		//-- Fix for a bug where a box of 1 or 2 pixels width or height would draw oddly.
		if((intRectRight - intRectLeft) > 2 && (intRectBottom - intRectTop) > 2) {
	    objMapCanvas.drawRect(intRectLeft, intRectTop, intRectRight - intRectLeft, intRectBottom - intRectTop);
	    objMapCanvas.paint();
  	}
};

/**
 * Finish drawing a rectangle and call its handler function in tools.js if its shape is valid.
*/
function draw_stopRect() {
    draw_stopDrag();
    //objMapCanvas.clear();
    draw_updateRect();

    //if((intRectRight - intRectLeft) > 1)
        TB_finishTool(intRectLeft, intRectTop, intRectRight, intRectBottom);
};

/**
 * Calculation the proper Right, Left, Bottom and Top positions of the rectangle.
*/
function draw_updateRect() {
    //-- The rectangle is to the right of the original point.
    if(intX1 > intX2) {
        intRectRight = intX1;
        intRectLeft = intX2;
    } else {
        intRectLeft = intX1;
        intRectRight = intX2;
    }

    //-- The original point clicked is above the original point.
    if(intY1 > intY2) {
        intRectBottom = intY1;
        intRectTop = intY2;
    } else {
        intRectTop = intY1;
        intRectBottom = intY2;
    }
};


/*########## LINE ######################*/
/**
 * Begin drawing a line (onmousedown)
*/
function draw_startLine(x, y) {
    draw_startDrag(x, y);
};

/**
 * Draw a line from the origin point to x, y (onmousemove)
*/
function draw_Line(x, y) {
    objMapCanvas.clear();
    draw_updateDrag(x, y);

    objMapCanvas.drawLine(intX1, intY1, intX2, intY2);
    objMapCanvas.paint();
};

/**
 * Finish drawing a line and call its handler function in tools.js if its shape is valid.
*/
function draw_stopLine() {
    draw_stopDrag();
    //objMapCanvas.clear();
    if(getDistance(intX1, intY1, intX2, intY2) > 0)
        TB_finishTool(intX1, intY1, intX2, intY2);
};


/*########## POLYLINE ######################*/
/**
 * Begin drawing a polyline (onmousedown)
*/
function draw_startPolyline(x, y) {
    if(!bolIsDragging) {
        arrXPoints = new Array();
        arrYPoints = new Array();
    }

    draw_startDrag(x,y);
    arrXPoints[arrXPoints.length] = x;
    arrYPoints[arrYPoints.length] = y;
};

/**
 * Draw a polyline from the last clicked point to x, y (onmousemove)
*/
function draw_Polyline(x, y) {
    objMapCanvas.clear();
    draw_updateDrag(x, y);

    objMapCanvas.drawPolyline(arrXPoints, arrYPoints);
    objMapCanvas.drawLine(intX1, intY1, intX2, intY2);
    objMapCanvas.paint();
};

/**
 * Finish drawing a polyline and call its handler function in tools.js if its shape is valid.
*/
function draw_stopPolyline() {
    draw_stopDrag();

    //objMapCanvas.clear();
    if(arrXPoints.length > 1 && getDistance(arrXPoints[0], arrYPoints[0], arrXPoints[1], arrYPoints[1]) > 1)
    		TB_finishPolyTool(arrXPoints, arrYPoints);
};


/*########## POLYGON ######################*/
/**
 * Begin drawing a polygon (onmousedown)
*/
function draw_startPolygon(x, y) {
    //-- Wipe the slate clean.
    if(!bolIsDragging) {
        arrXPoints = new Array();
        arrYPoints = new Array();
    }

    draw_startDrag(x, y);
    arrXPoints[arrXPoints.length] = x;
    arrYPoints[arrYPoints.length] = y;
};

/**
 * Draw a polygon from the last clicked point to x, y (onmousemove)
*/
function draw_Polygon(x, y) {
    objMapCanvas.clear();
    draw_updateDrag(x, y);

    var arrTempXPoints = new Array().concat(arrXPoints);
    var arrTemvpYPoints = new Array().concat(arrYPoints);
    arrTempXPoints[arrTempXPoints.length] = intX2;
    arrTemvpYPoints[arrTemvpYPoints.length] = intY2;

    objMapCanvas.drawPolygon(arrTempXPoints, arrTemvpYPoints);
    objMapCanvas.paint();
};

/**
 * Finish drawing a polygon and call its handler function in tools.js if its shape is valid.
*/
function draw_stopPolygon() {
    draw_stopDrag();

    //objMapCanvas.clear();
    if(arrXPoints.length > 2  && getDistance(arrXPoints[0], arrYPoints[0], arrXPoints[1], arrYPoints[1]) > 1) {
        arrXPoints[arrXPoints.length] = arrXPoints[0];
        arrYPoints[arrYPoints.length] = arrYPoints[0];
        TB_finishPolyTool(arrXPoints, arrYPoints);
    }
};



/*****************************************
        EVENT HANDLERS
*****************************************/
function TB_OnMouseDown(event) {
    if(!event) var event = window.event;

    if(!isLeftClick(event))
        return;

    getMouseCoordinates(event);

    //-- Ensure we aren't running over the top of one of the <div> elements used to do the drawing.
    //if(draw_CheckCanvas(event))
        TB_startTool(intMouseX, intMouseY); //-- Begin whatever action the tool does.
    return;
};

function TB_OnMouseUp(event) {
    if(!event) var event = window.event;

    //-- Stop drawing.
    if(bolIsDragging)
        TB_stopTool(intMouseX, intMouseY);
    return false;
};


function TB_OnDoubleClick(event) {
    if(!event) var event = window.event;

    //-- Stop drawing polygon or poyline.
    if(bolIsDragging)
        TB_stopPolyTool();
    return false;
};


/**
 * Handles the dragging action for all tools.
 * Smoothes out the animation by spacing out the drawing with setTimeout.
*/
var mouseMove;
var intMoveCount = 0;
var intMoveTimeout = 0;
function TB_OnMouseMove(event) {
    if(!event) var event = window.event;

    mouseMove = function() {
        TB_CallOnMouseMove({intMouseX:intMouseX, intMouseY:intMouseY});
        get_LatLong();
    };

    //-- Ensure we aren't running over the top of one of the <div> elements used to do the drawing.
    //if(draw_CheckCanvas(event)) {
        getMouseCoordinates(event);
        clearTimeout(intMoveTimeout);
        intMoveCount++;

        if(intMoveCount <= 3) {
            intMoveTimeout = setTimeout(mouseMove, 80);
        } else {
            mouseMove();
            intMoveCount = 0;
        }
    //}

    return false;
};

function TB_CallOnMouseMove(objMouse) {
    if(bolIsDragging)
        TB_dragTool(objMouse.intMouseX, objMouse.intMouseY);
    return false;
};