/**
 * Map Javascript
 *
 * $Id: rubberband.js,v 1.2 2007-06-12 12:48:28 cybic Exp $
 */

 /**
  * Zoom Rubberband
  * @author: Oystein Steimler
  */

/** BEGIN CLASS DEFS **/

/**
 * Point - class defining a point in a coordinate system
 */
function Point( x, y ) {
    this.x = x;
    this.y = y;
}

function getX() {
    with ( this ) return x;
}

function getY() {
    with ( this ) return y;
}

function subtract( point ) {
    
    with ( this ) x -= point.getX();
    with ( this ) y -= point.getY();
}

function getPixels() {

    with ( this ) return "" + x + "|" + y;

}

function toString() {
    
    with ( this ) return "(" + this.getX() + "," + this.getY() + ")" ;
    
}

/* Bind methods to the Point class */
Point.prototype.getX = getX;
Point.prototype.getY = getY;
Point.prototype.subtract = subtract;
Point.prototype.getPixels = getPixels;
Point.prototype.toString = toString;

/**
 * RubberBand - class defining the geometrical properties of
 * a image drag rubberband
 */
function RubberBand( element, start ) {
    
    /* Store the rubberband div-element */
    this.element = element;
    
    /* Store start and stop point */
    this.startPoint = start;
    this.stopPoint = start;
    
}

/**
 * Set the start point of the rubber band
 */
function setStart( point ) {
    
    /* Store the start point */
    this.startPoint = point;
    
}

/**
 * Set the stop point of the rubber band
 */
function setStop( point ) {
    
    /* Store the stop point */
    this.stopPoint = point;
    
}

/**
 * Get the leftmost X-coordinate of the rubberband
 */
function getLeft() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the leftmost x-value from start and stop point */
	with ( this ) return Math.min( this.startPoint.getX(), this.stopPoint.getX() );
	
    } else {
    	
    	return -1;
	
    }
    
    
}

/**
 * Get the topmost Y-coordinate of the rubberband
 */
function getTop() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the topmost y-value from start and stop point */
	with ( this ) return Math.min( this.startPoint.getY(), this.stopPoint.getY() );
	
    } else {
	
        return -1;
	
    }
    
}

/**
 * Get the rightmost X-coordinate of the rubberband
 */
function getRight() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the leftmost x-value from start and stop point */
	with ( this ) return Math.max( this.startPoint.getX(), this.stopPoint.getX() );
	
    } else {
    	
    	return -1;
	
    }
    
    
}

/**
 * Get the Y-coordinate of the bottom of the rubberband
 */
function getBottom() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the topmost y-value from start and stop point */
	with ( this ) return Math.max( this.startPoint.getY(), this.stopPoint.getY() );
	
    } else {
	
        return -1;
	
    }
    
}

/**
 * Get the width of the rubberband
 */
function getWidth() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the horizontal distance between start and stop point */
	with ( this ) return Math.abs( this.startPoint.getX() - this.stopPoint.getX() );
	
    } else {
	
	return -1;
	
    }
    
}

/**
 * Get the height of the rubberband
 */
function getHeight() {
    
    if ( typeof this.stopPoint != 'undefined' ) {
	
	/* Return the vertical distance between start and stop point */
	with ( this ) return Math.abs( this.startPoint.getY() - this.stopPoint.getY() );
	
    } else {
	
	return -1;
	
    }
    
}

/**
 * Is this rubberband small enough to be a click
 */
function isClick() {

    return ( this.getWidth() < 10 && this.getHeight() < 10 );

}

/**
 * Get a formatted string for the POST'ed form
 */
function getFormData() {
    
    if ( this.isClick() ) {
	
	/* Treat the rubberband as a click */
	return "" + this.startPoint.getX() + "@" + this.startPoint.getY();
	
    } else {
	
	/* Treat the rubberband as a dragged box */
	return "" + this.getLeft() + "@" + this.getTop() + "@" + this.getRight() + "@" + this.getBottom();
	
    }
    
}

/**
 * Show the rubberband
 */
function show() {
    
    this.element.style.visibility = 'visible';
    
}

/**
 * Hide the rubberband
 */
function hide() {
    
    this.element.style.visibility = 'hidden';
    
    
}

/**
 * Redraw the rubberband between the current start
 * and stop point.
 */
function redraw() {
    
    /* Get rubberband elements style */
    var elementStyle = this.element.style;
    
    /* Update the element's position properties */
    elementStyle.left = this.getLeft() + 'px';
    elementStyle.top = this.getTop() + 'px';
    elementStyle.width = this.getWidth() + 'px';
    elementStyle.height = this.getHeight() + 'px';
    
}

/* Bind methods to the RubberBand class */
RubberBand.prototype.setStart = setStart;
RubberBand.prototype.setStop = setStop;
RubberBand.prototype.getLeft = getLeft;
RubberBand.prototype.getTop = getTop;
RubberBand.prototype.getRight = getRight;
RubberBand.prototype.getBottom = getBottom;
RubberBand.prototype.getWidth = getWidth;
RubberBand.prototype.getHeight = getHeight;
RubberBand.prototype.show = show;
RubberBand.prototype.hide = hide;
RubberBand.prototype.redraw = redraw;
RubberBand.prototype.isClick = isClick;
RubberBand.prototype.getFormData = getFormData;

/** END OF CLASS DEFS **/

var className;

/**
 * Submit the main form with a direction in the clickDir field
 * 
 * FIXME: This might not be needed anymore
 */
function directionClick(direction)
{
    document.getElementById('clickDir').value = direction;
    document.getElementById('frmMain').submit();
    formSubmit();
}

/**
 * Submit the main form with a zoomlevel in the zoomLevel field
 *
 * FIXME: This might not be needed anymore
 */
function zoomClick(level)
{
    document.getElementById('zoomLevel').value = level;
    document.getElementById('frmMain').submit();
    formSubmit();
}


/**
 * Avoid submitting the form using the enter button
 */
function formSubmit( event ) {

    if ( !event ) var event = window.event;
    
    /* Avoid submitting the form using the enter key */

    if ( typeof event == 'keydown' && event.keyCode == 13 ) {

	search(); // XXX: Do we need this?!
	return false;

    }
    
}

/**
 * Submit the form to perform changes (zoom, pan, rubberband-zoom)
 */
function submit() {
    
    document.getElementById('frmMain').submit();
    
}

/**
 * Show the "Loading map..." box
 */
function showLoading() {
    /* Set mouse cursor */
    document.body.style.cursor='wait';
    
    /* Show the "Loading map..." progress bar */
    document.getElementById('loading').style.visibility = 'visible';
}

/**
 * Disable firing a click using the enter key
 * XXX: This might be redundant along with the formSubmit()
 */
function noenter( event ) {
    
    if ( !event ) {
	var event = window.event;
	
    }
    
    if ( typeof event == 'keypress' && event.keyCode == 13 ) {
	search(); // FIXME: Do we need this?!
	return false;
    }
    
}


/**
 * Determine if the event is a "right button click"
 */
function isRightButton(evt) {
    var i = 1;
    //if (evt.which)
    //	i = evt.which;
    //else
    i = evt.button;
    return (i == 2);
}


/*
 * Rubberband zoom functions
 */

var rubberBand = null;
var mapCoords = null;

/**
 * mouseDown - stard drag'n'drop of rubberband area
 */			
function mapMouseDown( evt ) {
    
    /* IE quirk */
    if ( !evt ) {
	var evt = window.event;
    }
    
    /* XXX: What does it do?! */
    if ( isRightButton( evt ) ) {

	var mouseCoords = getMouseMapCoords( evt );

	/* alert( mouseCoords.getPixels() ); */

	document.getElementById('frmMain').pixels.value = mouseCoords.getPixels();
	return false;
    }
    
    /* Store the coordinates of the map */
    mapCoords = findObjCoords( 'ibtnMap', 'wrapper' );


	 //alert( mapCoords.toString() ); 
    
    /* Start the rubberband with current coords as starting point */  
    rubberBand = new RubberBand( document.getElementById( 'rubberBand' ), getMouseMapCoords( evt ) );
    
    rubberBand.show();
    
    /* Defeat further event handling */
    return false;
    
}

/**
 * mouseMove - update rubberband drags
 */
function mapMouseMove( evt ) {
    
    if (rubberBand == null)
	return false;
    
    var mouseCoords = getMouseMapCoords( evt );
    
    rubberBand.setStop( mouseCoords );
    rubberBand.redraw();
    
    return false;
    
}

/**
 * MouseUp - Finish drag'n'drop and complete rubberband zoom
 */
function mapMouseUp( evt ) {
    
    if (rubberBand == null)
	return false;
    
    
    /* Hide the rubberband, and fire up the progress bar eyecandy */
    rubberBand.hide();
    showLoading();
    
    /* Store rubberband data in the form */
    document.getElementById('frmMain').pixels.value = rubberBand.getFormData();

    if ( rubberBand.isClick() ) {

	/* This is a click */
	document.getElementById('frmMain').cmd.value = "center";

    } else {

	/* This is a rubberband zoom */
        document.getElementById('frmMain').cmd.value = "rubber";

    }
    
    /* Destroy the rubberband */
    rubberBand = null;

    /* Submit the form */
    submit();
    
}

/**
 * Fetch mouse coordinates - relative to the map origo defined by
 * the mapCoords Point.
 */
function getMouseMapCoords( event ) {
    
    if ( !event ) {
	
	var event = window.event;
	
    }
    
    /* Get Mouse coordinates */
    var mousePos = getMouseCoords( event );
    
    /* Subtract map coordinates */  
    mousePos.subtract( mapCoords );
    
    return mousePos;
    
}

/**
 * Fetch the mouse coordinates relative to the page
 */
function getMouseCoords ( e ) {
    
    var posx = 0;
    var posy = 0;
    
    if (!e) var e = window.event;
    
    if ( e.pageX || e.pageY ) {
	posx = e.pageX;
	posy = e.pageY;
    }
    
    else if ( e.clientX || e.clientY ) {
	posx = e.clientX + document.body.scrollLeft;
	posy = e.clientY + document.body.scrollTop;
    }

    window.status = posx + '@' + posy;
    
    return new Point( posx, posy );
    
}

/**
 * Find an elements coordinates relative to a containing element (origo)
 */
function findObjCoords( name, origo ) {
    
    var curX = 0;
    var curY = 0;

    var debugString = "";
    
    /* Walk the tree downwards until you reach the origo element */
    for ( var obj = document.getElementById( name );
	  obj.tagName != 'BODY' &&
	  obj.id.toLowerCase() != origo;
	  //obj.offsetParent;
	  obj = obj.offsetParent ) {
	
	/* sum offsets */

	curX += obj.offsetLeft;
	curY += obj.offsetTop;

	debugString += "" + obj.id + " - " + obj.offsetLeft + ":"+ obj.offsetTop + "\n";

	
    }
    
    if ( curX == 0 && obj.x ) {
	
	/* The obj has no offsetParent but has got x */
	
	curX = obj.x + window.scrollBarX;
	curY = obj.y;

	debugString = "JALLA!";
	
    }
    
//   alert( debugString );

    /* Return a point defining the element top-left position */
    return new Point( curX, curY );
    
}
