/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
var UI_VIEW_NOT_SCROLLING = 0;
var UI_VIEW_MOUSE_DOWN_SCROLL = 1;
var UI_VIEW_KEY_DOWN_SCROLL = 2;

//========================================================================
// BEGIN: UIPap Class
//========================================================================

	function UIView(containerId, zIndex)
	{
		uiViewInit(this);
		this.containerId = containerId;
		if(zIndex)
			this.viewport.zIndex = zIndex;
	}

	function uiViewInit(object)
	{
	// INHERIT
		uiWidgetInit(object);

	// MEMBER VARIABLES
		object.domElemId 		= "uiView." + object.id;
		object.containerId 		= null;
		object.viewport 		= {domElemId: object.domElemId + ".viewport", background: "white", border: "1px solid black",  zIndex: 0};
		object.canvas   		= {domElemId: object.domElemId + ".canvas"};
		object.bitmap			= {};
		object.tools   			= {};

		object.scroll			= { state:		UI_VIEW_NOT_SCROLLING,
									keyDown:	"noKey",	// Equivalent for mousedown
									delta:		0,  			// For arrow key scrolling step size
									mousePos:	{screenX: 0, screenY: 0}
								};

	// INTERNAL METHODS
		object.build 			= uiViewBuildHTML;
		object.buildItems		= uiViewBuildItems;
		object.moveCanvas		= uiViewMoveCanvas;

		object.mousedown  		= uiViewMousedown;
		object.mouseup  		= uiViewMouseup;
		object.mousemove		= uiViewMousemove;
		object.mousewheel		= uiViewMousewheel;
		object.keydown			= uiViewKeydown;
		object.keyup			= uiViewKeyup;

	// PUBLIC METHODS
		object.setup			= uiViewSetup;
		object.adjustLayout		= uiViewAdjustLayout;
		object.adjustTools		= null;		// If present, called during adjustLayout()
	}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

function uiViewBuildHTML()
{
	this.viewport.domElem = null;
	this.viewport.bounds = undefined
	this.canvas.domElem = null;
	this.tools.domElem = null;

	var containerDomElem = GetDomElem(this.containerId);
	if(containerDomElem) {
		containerDomElem.position = "relative";		// Can't make overflow work with absolute;
		containerDomElem.innerHTML = "Working ... " + this.domElemId;
	}

	if(this.adjustLayoutTimeout)
		clearTimeout(this.adjustLayoutTimeout);

	this.scroll.state = UI_VIEW_NOT_SCROLLING;

	if(this.buildItemData)
		this.buildItemData();

	// Build the Viewport that is the window
	this.addHTML('<div id="' + this.viewport.domElemId + '"')
	this.addHTML('style="position: absolute; overflow: hidden; ');
	if(this.viewport.background)
		this.addHTML( 'background: ' + this.viewport.background + '; ');
	if(this.viewport.border)
		this.addHTML( 'border: ' + this.viewport.border + '; ');
	if(this.viewport.width)
		this.addHTML('width: ' + this.viewport.width + 'px; ');
	if(this.viewport.height)
		this.addHTML('height: ' + this.viewport.height + 'px; ');
	this.addHTML('z-index: ' + this.viewport.zIndex + '; ');
	this.addHTML('" ');			// End style
	this.addHTML('onMousedown="GetUiElem(' + this.id + ').mousedown(this,event); UiCancelEvent(event);" ');
	this.addHTML('onMouseup="GetUiElem(' + this.id + ').mouseup(this,event); UiCancelEvent(event);" ');
//	this.addHTML('onMouseout="GetUiElem(' + this.id + ').mouseup(this,event);" ');
	this.addHTML('onMousemove="GetUiElem(' + this.id + ').mousemove(this,event);" ');
	this.addHTML('onMousewheel="GetUiElem(' + this.id + ').mousewheel(this,event);" ');
	this.addHTML('onKeydown="GetUiElem(' + this.id + ').keydown(this,event)" ');
	this.addHTML('onKeyup="GetUiElem(' + this.id + ').keyup(this,event)" ');
	this.addHTML('>');

	// Build the canvas that is under/inside the viewport
	this.addHTML('<div id="' + this.canvas.domElemId +'" ');
	this.addHTML('style="display: none; position: absolute; ');
	if(this.canvas.background)
		this.addHTML('background: ' + this.canvas.background + '; ');
	if(this.canvas.border)
		this.addHTML('border: ' + this.canvas.border + '; ');
	if(this.canvas.left)
		this.addHTML('left: ' + this.canvas.left + '; ');
	if(this.canvas.top)
		this.addHTML('top: ' + this.canvas.top + '; ');
	this.addHTML('width: ' + this.canvas.width + 'px; ');
	this.addHTML('height: ' + this.canvas.height + 'px;" ');
	this.addHTML('>\n');

	if(this.buildItems) {
		if(this.tools.domElemId && this.bitmap.width && this.bitmap.height)
		{
			this.addHTML('<div id="' + this.bitmap.domElemId + '.hotSpot" ');
			this.addHTML('style="position: absolute; display: block; background: transparent; overflow: hidden; '
				+ 'width: ' + this.bitmap.width + '; height: ' + this.bitmap.height + '"></div>')
		}
		this.buildItems();
		this.addHTML('<img id="' + this.domElemId + '.overlay" ');
		this.addHTML('onMousedown="GetUiElem(' + this.id + ').overlayEvent(event);" ');
		this.addHTML('onMouseup="GetUiElem(' + this.id + ').overlayEvent(event);" ');
		this.addHTML('onContextMenu="GetUiElem(' + this.id + ').overlayEvent(event)" ');
		this.addHTML('onMousemove="GetUiElem(' + this.id + ').overlayEvent(event)" ');
		this.addHTML('style="position: absolute; display: none; z-index: 30000; background: transparent;" ');
		this.addHTML('></img>')
	}

	if(!this.bitmap.isScrolling)
		this.addHTML('</div>');		// End canvas (bitmap is fixed in viewport)

	if(this.bitmap.width && this.bitmap.height) {
		this.addHTML('<img id="' + this.bitmap.domElemId + '" onselect="UiCancel(event)" src="" ');
		this.addHTML(' style="display: none;"></img>');
		this.canvas.bounds = {top: 0, left: 0, bottom: parseInt(this.bitmap.height), right: parseInt(this.bitmap.width)};
	}

	if(this.bitmap.isScrolling)
		this.addHTML('</div>');		// End canvas (bitmap moves with canvas)

	if(this.tools.domElemId) {
		this.addHTML('<div style="position: absolute; z-index: ' + (this.viewport.zIndex+1) + '; "');
		this.addHTML('id="' + this.tools.domElemId +'">');
		if(this.buildTools)
			this.buildTools();
		this.addHTML('</div>');
	}

	this.addHTML('</div>');			// End main viewport

	this.adjustLayout(0);
}

function uiViewBuildItems()
{
}

UIView.prototype.overlayEvent = function(type, event)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Routines that assist in the scrolling of the canvas that contains the map items.  The canvas
// is in the viewport that has scrollbars when the canvas size exceeds the size of the viewport
////////////////////////////////////////////////////////////////////////////////////////////////////

var debugScroll2 = false;

function uiViewMousedown(domElem, event)
{
	if(event.button > 1)	// Only leftmost button allowed
		return;

	UiCancelEvent(event);

	this.mouseupCounter = gMouseupCounter;

	if(this.isInteractiveItems && this.selector && !event.altKey) {
		this.selector.start(this, this.viewport.domElemId, event);
		return;
	}

	domElem.style.cursor = "move";
	this.scroll.state = UI_VIEW_MOUSE_DOWN_SCROLL;
	this.scroll.mousePos = {screenX: event.screenX, screenY: event.screenY};
	this.scroll.mouseDownScreen = {left: event.screenX, top: event.screenY};
	this.scroll.mouseDownCanvas = {left: this.canvas.left, top: this.canvas.top};
	if(debugScroll2)DebugText("MouseDOWN: ");

}

function uiViewMouseup(domElem, event)
{
	UiCancelEvent(event);

	if(this.isMouseActive) {
		this.isMouseActive = false;
		this.selectDomElem.style.display = "none";
		return;
	}

	if(this.scroll.state == UI_VIEW_NOT_SCROLLING)
		return;

	if(this.moveCanvasDone)
		this.moveCanvasDone();

	var x = event.clientX + document.body.scrollLeft - GetAbsLeft(domElem) + this.canvas.left;
	var y = event.clientY + document.body.scrollTop - GetAbsTop(domElem) + this.canvas.top;
//alert(this.domElemId + ": x=" + x + ", y=" + y + ", clientX=" + event.clientX + ", clientY=" + event.clientY + ", scrollTop=" + document.body.scrollTop + ", scrollLeft=" + document.body.scrollLeft);
	domElem.style.cursor = "";
	this.scroll.state = UI_VIEW_NOT_SCROLLING;
	if(debugScroll2)DebugText("MouseUP: ");
}

function uiViewMousemove(domElem, event)
{
	if(this.mouseupCounter != gMouseupCounter || (this.scroll.state == UI_VIEW_KEY_DOWN_SCROLL && !event[this.scroll.keyDown])) {
		if(debugScroll2)DebugText("MOUSEMOVE:  end  alt-scroll condition --> call mouseUp()");
		this.mouseup(domElem,event);
		return;
	}

	if(this.scroll.state != UI_VIEW_NOT_SCROLLING) {
		if(!this.canvas.domElem)
			this.canvas.domElem = GetDomElem(this.canvas.domElemId);
		var left = this.canvas.domElem.offsetLeft + event.screenX - this.scroll.mousePos.screenX;
		var top = this.canvas.domElem.offsetTop + event.screenY - this.scroll.mousePos.screenY;
		if(debugScroll2)DebugText("left=" + left + " = " + this.canvas.domElem.offsetLeft + " + " + event.screenX + " - " + this.scroll.mousePos.screenX);
		if(debugScroll2)DebugText("top=" + top + " = " + this.canvas.domElem.offsetTop + " + " + event.screenY + " - " + this.scroll.mousePos.screenY);

		if(debugScroll2)DebugText("MOUSEMOVE:  left=" + left, + "top="+top);
		this.scroll.mousePos = {screenX: event.screenX, screenY: event.screenY};

		if(false) {
			left = this.scroll.mouseDownCanvas.left + (event.screenX - this.scroll.mouseDownScreen.left)
			top = this.scroll.mouseDownCanvas.top + (event.screenY - this.scroll.mouseDownScreen.top)
			this.mouseMoveLatest = {left: left, top: top};
			this.mouseMoveTimeout = uiViewMouseMoveTimeout;
			if(!this.mouseMoveTimer)
				this.mouseMoveTimer = setTimeout(GetGlobalName(this) + ".mouseMoveTimeout()", 100);
		}
		else {
			this.moveCanvas(left, top);
			if(this.moveCanvasDone)
				this.moveCanvasDone();
		}
	}
	else {
		if(debugScroll2)DebugText("MOUSEMOVE:  NOT SCROLLING");
		if(event[this.scroll.keyDown]) {
			this.mousedown(domElem,event);
			this.scroll.state = UI_VIEW_KEY_DOWN_SCROLL;
		}
	}
}

function uiViewMouseMoveTimeout()
{
	this.mouseMoveTimer = null;
	this.moveCanvas(this.mouseMoveLatest.left, this.mouseMoveLatest.top);
	if(this.moveCanvasDone)
		this.moveCanvasDone();
}


function uiViewMousewheel(domElem, event)
{
	var delta = Math.round(this.scroll.delta * event.wheelDelta/240);
	if(event.shiftKey)
		this.moveCanvas(-delta, 0, true);
	else
		this.moveCanvas(0, delta, true);

	if(this.moveCanvasDone)
		this.moveCanvasDone();
}

function uiViewKeydown(domElem, event)
{
	if(this.scroll.state != UI_VIEW_KEY_DOWN_SCROLL && event[this.scrollKeyDown]) {
		this.mouseDown(domElem,event);
		this.scroll.state = UI_VIEW_KEY_DOWN_SCROLL;
	}
	else {
		var delta = this.scroll.delta;
		if(delta) {
			switch(event.keyCode) {
				case 38:	this.moveCanvas(0, delta, true);	break;
				case 40:	this.moveCanvas(0, -delta, true);	break;
				case 37:	this.moveCanvas(delta, 0, true);	break;
				case 39:	this.moveCanvas(-delta, 0, true);	break;
			}
			if(this.moveCanvasDone)
				this.moveCanvasDone();

		}
	}
}
function uiViewKeyup(domElem, event)
{
	if(this.scroll.state == UI_VIEW_KEY_DOWN_SCROLL && !event[this.scroll.keyDown])
		this.mouseup(domElem, event);
}

function uiViewMoveCanvas(left, top, relativeMove)
{
	if(this.canvas.isMoveActive || !this.canvas.domElem)
		return;

	this.canvas.isMoveActive = true;

	if(!this.canvas.domElem)
		this.canvas.domElem = GetDomElem(this.canvas.domElemId);
//DebugText("MOVE CANVAS: left=" + left + ", top=" + top + "FROM: left=" + this.canvas.domElem.style.left + ", top=" + this.canvas.domElem.style.top);

	var bounds = this.canvas.bounds;
	var style  = this.canvas.domElem.style;

	if(relativeMove) {
		left += parseInt(style.left);
		top  += parseInt(style.top);
	}
	style.left = left; //Math.max(bounds.left-bounds.right+10,  Math.min(left,bounds.right-10));
	style.top  = top; // Math.max(bounds.top-bounds.bottom+10,   Math.min(top,bounds.bottom-10));

	this.canvas.left = left;
	this.canvas.top = top;

	this.canvas.isMoveActive = false;
}


//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

function uiViewSetup(width, height, canvasBounds) {
	this.viewport.width = width;
	this.viewport.height = height;
	this.canvas.bounds = canvasBounds;
	this.resetHTML();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//	Adjust the size and position of the viewport and its contents.  The sizing must wait until the
// 	browser has rendered the the HTML for the viewport/canvas and its container.  This adjustment
//	routine keeps a setTimeout() and waits for the rendering to take place before adjusting
//	the viewport elements.
////////////////////////////////////////////////////////////////////////////////////////////////////

function uiViewAdjustLayout(timeOfFirstAttempt)
{
	if(!this.viewport.domElem)
		this.viewport.domElem = GetDomElem(this.viewport.domElemId);
	if(!this.canvas.domElem)
		this.canvas.domElem = GetDomElem(this.canvas.domElemId);

	var time = 0;
	var adjustNow = true;

	if(false && timeOfFirstAttempt) {
		time = new Date().getTime();
		adjustNow = time - timeOfFirstAttempt > 250; // Don't try to re-adjust viewport and canvas too often
	}

	if(adjustNow && this.viewport.domElem && this.canvas.domElem) {
		if(this.adjustViewport)
			this.adjustViewport();

		var style = this.viewport.domElem.style;
		if(this.viewport.sizeToContainer) {
			var containerDomElem = GetDomElem(this.containerId);
			var width = containerDomElem.offsetWidth;
			var height = containerDomElem.offsetHeight;
		}
		else {
			width  = parseInt(style.width);
			height = parseInt(style.height);
		}

		if(width && height) {
			if(this.viewport.sizeToContainer) {
				style.width  = width;
				style.height = height;
			}
			this.viewport.width = width;
			this.viewport.height = height;

			if(this.bitmap && this.bitmap.url && !(this.bitmap.width && this.bitmap.height)) {
				var domElem = GetDomElem(this.bitmap.domElemId);
				this.bitmap.width  = domElem.offsetWidth;
				this.bitmap.height = domElem.offsetHeight;
				if(!this.canvas.bounds)
					this.canvas.bounds = {left: 0, top: 0, right: this.bitmap.width, bottom: this.bitmap.height};
			}

			// Center the canvas in the viewport
			this.canvas.width = this.canvas.bounds.right - this.canvas.bounds.left;
			this.canvas.height = this.canvas.bounds.bottom - this.canvas.bounds.top;

			if(this.adjustCanvas)
				this.adjustCanvas();

			if(this.adjustTools)
				this.adjustTools();

			// The moveCanvasDone() has to be executed aftera delay or it doesn't show up.  The reason is
			// that adjustTools() usually creates HTML that has to be processed
			if(this.moveCanvasDone)
				setTimeout(GetGlobalName(this) + ".moveCanvasDone();", 50);

			this.canvas.domElem.style.display = "block";
			this.adjustLayoutTimeout = null;
			return;
		}
	}

	this.adjustLayoutTimeout = setTimeout(GetGlobalName(this) + ".adjustLayout(" + time + ")", 50);
}

function uiMapAdjustViewport()
{
	this.viewport.width = this.viewport.domElem.offsetWidth;
	this.viewport.height = this.viewport.domElem.offsetHeight;
	debugger;
}


UIView.prototype.selectArea = function(cmd, bounds)
{
}

//-----------------------------------------------------------------------------------------------------------------/


var xxx = false;

document.write('<div id="selectorContainer" style="display: none; position: absolute; top:0; left: 0; z-index: 200001;">&nbsp</div>');

function UIMouseSelect()
{
	uiMouseSelectInit(this);

	this.containerDomElemId = "selectorContainer";
}

function uiMouseSelectInit(object)
{
	uiElementInit(object);

	object.domElemId	= object.domElemId + ".selector";
	object.isMouseActive	= false;
	object.updateTime	= 0;
	object.absBounds	= null;

	object.build		= uiMouseSelectBuildHTML;
	object.start		= uiMouseSelectStart;
	object.stop			= uiMouseSelectStop;
	object.update		= uiMouseSelectUpdate;
	object.click		= uiMouseSelectClick;
	object.mousedown	= uiMouseSelectMousedown;
	object.mouseup		= uiMouseSelectMouseup;
	object.mousemove	= uiMouseSelectMousemove;
}

function uiMouseSelectBuildHTML()
{
	this.addHTML('<div id="' + this.domElemId + '" ');
	this.addHTML('style="')
	this.addHTML('display: none; position: absolute; overflow: hidden; ');
	if(true)
		this.addHTML('border: 2px Red dashed;');
	else
		this.addHTML('border: 1px Red solid; background: #FAA; filter: alpha(opacity=40); -moz-opacity:0.4;')

	this.addHTML('"></div>');
}
/**
 *
 */
function uiMouseSelectStart(uiClient, boundsDomElemId, startEvent)
{
	if(xxx)DebugText("--uiMouseSelectSTART" + "  x=" + startEvent.x + ", y=" + startEvent.y + ", button=" + startEvent.button);
	this.uiClient = uiClient;
	this.containerDomElem = GetDomElem(this.containerDomElemId);

	this.selectBounds = null;
	if(boundsDomElemId)
		this.selectBoundsLimit = GetAbsBounds(GetDomElem(boundsDomElemId));
	else
		this.selectBoundsLimit = null;

	this.pushHTML(this.containerDomElem);
	this.containerDomElem.style.display = "block";

	this.selectionDomElem = GetDomElem(this.domElemId);

	this.startEvent = startEvent;
	this.e0 = null;

	UiHidePopups();
	UiMouseExclusiveClient(this);

	this.isMouseActive = true;
	this.uiClient.selectArea("start");
}

function uiMouseSelectStop(event)
{
	UiMouseExclusiveClient(null);

	this.isMouseActive = false;
	this.selectionDomElem.style.display = "none";
	this.selectionDomElem.innerHTML = "";

	if(this.selectBounds)
		this.uiClient.selectArea("update", this.selectBounds, this.isSelectOn);
	this.uiClient.selectArea("end");
}

function uiMouseSelectUpdate(event)
{
	var time = new Date().getTime();
	if(time - this.updateTime > 50) {
		this.uiClient.selectArea("update", this.selectBounds, this.isSelectOn);
		this.updateTime = time;
	}
}
/**
 *
 */
function uiMouseSelectCaptureEvents(isCapture)
{
	UiMouseExclusiveClient(isCapture ? this : null);
}
/**
 *	Event Handlers
 */
function uiMouseSelectClick(event)
{
	this.stop();	// Needed because some mouse ups are sent as a click by IE.
}

function uiMouseSelectMousedown(event)
{
	event.cancelBubble = true;
	return false;
}

function uiMouseSelectMouseup(event)
{
	var e = UiMouseEvent(event);
	if(xxx)DebugText("--uiMouseSelectMouseup" + "  x=" + e.x + ", y=" + e.y + ", button=" + event.button);

	event.cancelBubble = true;

	if(event.button != 2)
		this.stop(event)

	return false;
}

function uiMouseSelectMousemove(event)
{
	var e1 = UiMouseEvent(event);
	if(xxx)DebugText("----uiMouseSelectMousemove" + "  x=" + e1.x + ", y=" + e1.y + ", button=" + event.button);

	if(!this.isMouseActive)
		return true;

	if(!this.e0) {
		if(!this.startEvent)
			this.startEvent = event;
		this.isSelectOn = !this.startEvent.ctrlKey;
		this.e0 = e1;
	}

	var left	= Math.min(e1.x, this.e0.x);
	var top		= Math.min(e1.y, this.e0.y);
	var bottom	= Math.max(e1.y, this.e0.y);
	var right	= Math.max(e1.x, this.e0.x);
	var bounds = {top: top, left: left, bottom: bottom, right: right};

	if(this.selectBoundsLimit) {
		left 	= Math.max(left, this.selectBoundsLimit.left);
		top 	= Math.max(top, this.selectBoundsLimit.top);
		bottom 	= Math.min(bottom, this.selectBoundsLimit.bottom);
		right 	= Math.min(right, this.selectBoundsLimit.right);
	}

	var style = this.selectionDomElem.style;
	style.top = top;
	style.left = left;
	style.width = Math.max(right-left,1) + "px";
	style.height = Math.max(bottom-top,1) + "px"
	style.display = "block";

	this.selectBounds = {top: top, left: left, bottom: bottom, right: right};
	this.update(event);

	event.cancelBubble = true;
	event.returnValue = false;
}
