/**
 *	public Javascript Class Map
 *
 *	@author		Warwick Bambrook
 *
 */
 
function Map(parent, width, height, filename) {
	this.init(parent, width, height,filename);
}

Map.instanceCount = 0;

Map.prototype.init = function (parent, width, height, filename) {
	this.type = 'Map';
	this.width = width;
	this.height = height;
	this.currentTool='panTool';
	this.forgroundImage='';
	this.backgroundImage='';
	this.zoomWidth=0;
	this.mouseOverMap=false;
	this.mouseIsDown=false;
	this.selectBox = new SelectBox(width,height);
	this.geoFence = new GeoFence(this.width/2,this.height/2,40);
	this.panx=0;
	this.pany=0;
	this.offsetTop=0;
	this.offsetLeft=0;
	// ID of parent element
	this._parent = parent;
	this.animating = false;
	Event.observe(document, "mousedown", this._mousedown.bindAsEventListener(this));
	Event.observe(document, "mousemove", this._mousemove.bindAsEventListener(this));
	Event.observe(document, "mouseup", this._mouseup.bindAsEventListener(this));
	this.setTool();
	this.getOffsets();
	this.draw(filename);
};

Map.prototype.draw = function (filename) {

		var map2 = document.createElement('div');
		map2.id="map2";
		map2.style.position = "absolute";
		map2.style.width=0;
		map2.style.height=0;
		document.getElementById(this._parent).appendChild(map2);
		
		var backgroundImage = document.createElement("img");
		backgroundImage.src="./streamimage.jsp?imageFilename=" + filename;
		backgroundImage.alt="";
		backgroundImage.width=this.width;
		backgroundImage.height=this.height;
		Element.setStyle(backgroundImage, {width: 500, height: 400, visibility:'hidden'});

		map2.appendChild(backgroundImage);
	
		var map1 = document.createElement('div');
		map1.id="map1";
		Element.setStyle(map1,{position:'absolute',width:0,height:0});
		document.getElementById(this._parent).appendChild(map1);

		var forgroundImage = document.createElement("img");
		forgroundImage.src="./streamimage.jsp?imageFilename=" + filename;
		forgroundImage.alt="";
		forgroundImage.width=this.width;
		forgroundImage.height=this.height;
		this.forgroundImage = forgroundImage;
		map1.appendChild(forgroundImage);
//		Element.setStyle(forgroundImage, {width: 700, height: 500});
		
		var wzCanvas = document.createElement('div');
		Element.setStyle(wzCanvas,{position:'absolute',width: this.width, height: this.height, zIndex:4000});
//		wzCanvas.style.position = "absolute";
//		wzCanvas.style.width=this.width;
//		wzCanvas.style.height=this.height;
//		wzCanvas.style.zindex=1;
		document.getElementById(this._parent).appendChild(wzCanvas);

		var loadingMessage = document.createElement('div');

		Element.setStyle(loadingMessage,{position:'absolute',top:175,left:225
				,width: 50,height:50,backgroundColor:0,borderColor:'darkRed',borderWidth:1
				,visibility:'hidden',zIndex:5000});
//		loadingMessage.style.position = "absolute";
//		loadingMessage.style.top=225;
//		loadingMessage.style.left=325;
//		loadingMessage.style.width=50;
//		loadingMessage.style.height=50;
//		loadingMessage.style.visibility="hidden";
//		loadingMessage.style.zIndex=5000;
		loadingMessage.id = "loadingMessage";
		document.getElementById(this._parent).appendChild(loadingMessage);

		var loadingImage = document.createElement('img');
		loadingImage.src = "./images/loading.gif";
		loadingImage.alt='Loading Map';
		loadingImage.width=50;
		loadingImage.height=50;
		loadingMessage.appendChild(loadingImage);
		
		// add selectBox		
		document.getElementById(this._parent).appendChild(this.selectBox._selectbox);
		
		// add geoFenceBox		
		document.getElementById(this._parent).appendChild(this.geoFence._geofence);
		
};

Map.prototype.fadeOut = function () {
	showLoadingMessage();
	this.animating = true;
	var forgroundImage = this.forgroundImage;
	new Effect.Opacity(forgroundImage, {duration:0.6, from:1.0, to:0.4});
};

/**
 * when the new map has been loaded this function will control the 
 * animation and show the new map in the forgroundImage 
 *
 * @param toImage this is the new image that is to be displayed
 */
Map.prototype.fadeIn = function (toImageUrl) {
	
	if (this.animating) {
//		alert(toImageUrl);
		setTimeout('map.fadeIn(\'' +  toImageUrl + '\')',1000);
	} else {
		var map1 = document.getElementById('map1');
		var map2 = document.getElementById('map2');
		
		// swap the forgroundImage image to the backgroundImage and show backgroundImage
		map2.innerHTML='';
		map2.style.left = map1.style.left;
		map2.style.top = map1.style.top;
		map2.style.width = map1.style.width;
		map2.style.height = map1.style.height;
		var swapImage = this.forgroundImage;
		swapImage.setAttribute("alt", "");
		this.backgroundImage = swapImage;
		map2.appendChild(this.backgroundImage);
		Element.show(this.backgroundImage);
		// remove forgound image and insert new image
		map1.innerHTML = '';
		var forgroundImage = document.createElement("img");
		forgroundImage.setAttribute("src", toImageUrl + "&rnd=" + Math.random());
		forgroundImage.setAttribute("alt", "forgroundImage Image");
		forgroundImage.setAttribute("width", this.width);
		forgroundImage.setAttribute("height", this.height);
		Element.setStyle(forgroundImage, {opacity: 0} );
		this.forgroundImage = forgroundImage;
		map1.appendChild(forgroundImage);
		
	//	alert('reset and ready container for forgroundImage image');
		map1.style.left = 0;
		map1.style.top = 0;
		map1.style.width = this.width;
		map1.style.height = this.height;
		Element.setStyle(this.forgroundImage, {width: 500, height: 400} );
		Element.setStyle(this.forgroundImage, {top: 0, left: 0} );
	
	//	alert('fade up the new image and fade off backgroundImage');
		// fade away backgroundImage and fade up forgroundImage
		new Effect.Parallel(
			    [ new Effect.Opacity(this.forgroundImage, {duration:1.0, from:0.0, to:1.0}),
			      new Effect.Opacity(this.backgroundImage, {duration:0.5, from:0.4, to:0.0})
			    ],{duration:1.0,afterFinish: hideLoadingMessage}
		);
	}
}

Map.prototype.centerMap = function(x,y) {
	new Effect.Move(this.forgroundImage, {x: x, y: y, mode:'relative', duration: 1.0, afterFinish: animationFinished});
}

Map.prototype.zoomIn = function(x,y,x1,y1) {
	this.animating = true;
	// calculate selectBox width and height
	var selectBoxWidth = x1-x;
	var selectBoxHeight = y1-y;
	var zoomFactor = this.width/selectBoxWidth;

							
	var bigMapWidth = (this.width*zoomFactor);
	var bigMapHeight = (this.height*zoomFactor);
	
	var mapCenterShiftX = (this.width - bigMapWidth)/2;
	var mapCenterShiftY = (this.height - bigMapHeight)/2;
	
	var mapCenterX = (this.width/2);
	var mapCenterY = (this.height/2);
	
	// get center of selectBox
	var selectBoxShiftX = (mapCenterX - ((x + x1)/2)) * zoomFactor;
	var selectBoxShiftY = (mapCenterY - ((y + y1)/2)) * zoomFactor;
				
	var mapShiftX = (mapCenterShiftX + selectBoxShiftX); 
	var mapShiftY = (mapCenterShiftY + selectBoxShiftY); 				

	new Effect.Parallel(
		[ new Effect.Scale(this.forgroundImage, zoomFactor*100)
		,new Effect.Move(this.forgroundImage, {x: mapShiftX, y: mapShiftY, mode:'relative'})
		],{ duration: 0.8,afterFinish: animationFinished }
	);
};

Map.prototype.zoomOut = function(x,y,x1,y1) {
	this.animating = true;
	
	var selectBoxWidth = x1-x;
	var selectBoxHeight = y1-y;
	var zoomFactor = (selectBoxWidth/this.width);

	var mapCenterShiftX = (this.width - selectBoxWidth) /2;
	var mapCenterShiftY = (this.height - selectBoxHeight) /2;
	
	var mapCenterX = (this.width/2);
	var mapCenterY = (this.height/2);
	// get center of selectBox
	var selectBoxShiftX = (mapCenterX - ((x + x1)/2)) * zoomFactor;
	var selectBoxShiftY = (mapCenterY - ((y + y1)/2)) * zoomFactor;

	var mapShiftX = (mapCenterShiftX + selectBoxShiftX); 
	var mapShiftY = (mapCenterShiftY + selectBoxShiftY); 

	new Effect.Parallel(
		[ new Effect.Scale(this.forgroundImage, (zoomFactor * 100) )
		,new Effect.Move(this.forgroundImage, {x: mapShiftX, y: mapShiftY, mode:'relative'})
		],{ duration: 0.8,afterFinish: animationFinished  }
	);
};

Map.prototype.isMouseOverMap = function(event) {
	var Mouse = new Object();
	Mouse.isOverMap=false;
	Mouse.x = 0;
	Mouse.y = 0;

	var offsetLeft = this.offsetLeft;
	var offsetTop = this.offsetTop;


	var scrollX;
	var scrollY;
	if (self.pageYOffset) // all except Explorer
	{
		scrollX = self.pageXOffset;
		scrollY = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
	{
		scrollX = document.documentElement.scrollLeft;
		scrollY = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		scrollX = document.body.scrollLeft;
		scrollY = document.body.scrollTop;
	}

	var actualX = event.clientX + scrollX ;
	var actualY = event.clientY + scrollY ;


	if ( (actualX > offsetLeft && actualX  < (offsetLeft + this.width))
		&& (actualY > offsetTop && actualY < (offsetTop + this.height) )) {
		Mouse.isOverMap=true;
		Mouse.x = actualX - offsetLeft;
		Mouse.y = actualY - offsetTop;
	} else {
		Mouse.isOverMap=false;
	}
//	window.status = "Event ("
//				+ event.clientX + "," + event.clientY + 
//			") scroll (" 
//				+ scrollX + "," + scrollY + 
//			") offsets (" 
//				+ offsetLeft + "," + offsetTop + 
//			") size (" 
//				+ this.width + "," + this.height + 
//			") Mouse (" 
//				+ Mouse.isOverMap + "," + Mouse.x + "," + Mouse.y + 
//			")";
	return Mouse;
};

Map.prototype.getOffsets = function() {
	var itsParent = document.getElementById(this._parent);
	
	var offsetTop = itsParent.offsetTop;
	var offsetLeft = itsParent.offsetLeft;

	while((itsParent = itsParent.offsetParent) != null) {
		offsetTop += itsParent.offsetTop;
		offsetLeft += itsParent.offsetLeft;
	}
	this.offsetTop = offsetTop;
	this.offsetLeft = offsetLeft;
};

Map.prototype.setTool = function(toolType) {
	this.currentTool = toolType;
};


//
// map events
//


/**
 *	map mousedown event 
 *
 * @param event the triggering event
 */
Map.prototype._mousedown = function (e) {
	var mouse;
	if (document.all) {
		mouse = this.isMouseOverMap(window.event);
	} else {
		mouse = this.isMouseOverMap(e);
	}

	if ( mouse.isOverMap ) {
		this.mouseIsDown=true;	
		if (this.currentTool =='geoTool') {
			this.geoFence._x = mouse.x;
			this.geoFence._y = mouse.y;
			this.geoFence.draw();
		}
		
		if (this.currentTool == 'panTool') {
			this.panx = mouse.x;
			this.pany = mouse.y;
		}
		if (this.currentTool == 'zoominTool' 
			|| this.currentTool == 'zoomoutTool') {
			
			this.selectBox._startx = mouse.x;
			this.selectBox._starty = mouse.y;
			this.selectBox._endx = mouse.x;	
			this.selectBox._endy = mouse.y;
			this.selectBox.draw();
			this.selectBox.showSelectBox();
		}
	}	
};

/**
 *	map mousemove event 
 *
 * @param event the triggering event
 */
Map.prototype._mousemove = function (e) {

	var mouse;
	if (document.all) {
		mouse = this.isMouseOverMap(window.event);
	} else {
		mouse = this.isMouseOverMap(e);
	}

	var map = document.getElementById('map');
	var map1 = document.getElementById('map1');
	if (mouse.isOverMap && this.mouseIsDown) {
		if (this.currentTool =='geoTool') {
			this.geoFence._x = mouse.x;
			this.geoFence._y = mouse.y;
			window.status="geoFence " + mouse.x + "," + mouse.y;
			this.geoFence.draw();
		}
		if (this.currentTool == 'panTool') {
//			window.status = 'x: ' + mouse.x + '  y:' + mouse.y
//			+ '  dx: ' + (mouse.x - this.panx) + '  dy:' + (mouse.y - this.pany);
			map1.style.left = mouse.x - this.panx; 
			map1.style.top  = mouse.y - this.pany;
		}
		if (this.currentTool == 'zoominTool'
				|| this.currentTool == 'zoomoutTool') {
			this.selectBox._endx = mouse.x;
			this.selectBox._endy = mouse.y;
			this.selectBox.draw();
		}
	}
	Event.stop(e);
};

/**
 *	map mouseup event 
 *
 * @param event the triggering event
 */
Map.prototype._mouseup = function (e) {
	var mouse;
	if (document.all) {
		mouse = this.isMouseOverMap(window.event);
	} else {
		mouse = this.isMouseOverMap(e);
	}
	
	if (mouse.isOverMap && this.mouseIsDown) {
		if (this.currentTool =='geoTool') {
			Utilities.getMapPoint(mouse.x,mouse.y,gotMapPoint);
		}

		if (this.currentTool == 'panTool') {
//			window.status="calling panMap(" + (mouse.x - this.panx) + "," + (mouse.y - this.pany) + ")";
			this.fadeOut();
			Navigation.panMap(
					(mouse.x - this.panx)
					,(mouse.y - this.pany)
					,panFinished);
		}
		if (this.currentTool == 'centerTool') {
//			window.status="calling centerMap(" + ((this.width/2)- mouse.x) + "," + ((this.height/2)-mouse.y) + ")";
			this.fadeOut();
			Navigation.panMap(
					((this.width/2)- mouse.x)
					,((this.height/2)- mouse.y)
					,centerFinished);
			this.centerMap(((this.width/2)- mouse.x),((this.height/2)-mouse.y));
		}
		if (this.currentTool == 'infoTool') {
			Utilities.getInfoAtPoint('GPSPoints',mouse.x,mouse.y,infoReceived);
		}
		if (this.currentTool == 'zoominTool' || this.currentTool == 'zoomoutTool') {
			this.fadeOut();
			var bounds = this.selectBox.getBoxBounds();
			if ((bounds.x2 - bounds.x1) < (this.width/20)) {
				var centerX = (bounds.x1+bounds.x2)/2;
				var centerY = (bounds.y1+bounds.y2)/2;
				var boundsWidth = this.width/4;
				var boundsHeight = this.height/4;
				bounds.x1 =	centerX - boundsWidth;
				bounds.y1 = centerY - boundsHeight;
				bounds.x2 = centerX + boundsWidth;
				bounds.y2 = centerY + boundsHeight;
			}
			if (this.currentTool == 'zoominTool') {
//				window.status="calling zoominMap(" + bounds.x1 + "," + bounds.y1 + "," + bounds.x2 + "," + bounds.y2 + ")";
				this.fadeOut();
				Navigation.zoominMap(
					bounds.x1,
					bounds.y1,
					bounds.x2,
					bounds.y2,
					zoominFinished);
				this.selectBox.hideSelectBox();
				this.zoomIn(bounds.x1,bounds.y1,bounds.x2,bounds.y2);
			}
		
			if (this.currentTool == 'zoomoutTool') {
//				window.status="calling zoomoutMap(" + bounds.x1 + "," + bounds.y1 + "," + bounds.x2 + "," + bounds.y2 + ")";
				Navigation.zoomoutMap(
					bounds.x1,
					bounds.y1,
					bounds.x2,
					bounds.y2,
					zoomoutFinished);
				this.selectBox.hideSelectBox();
				this.zoomOut(bounds.x1,bounds.y1,bounds.x2,bounds.y2);
			}
		}
	}
	this.mouseIsDown=false;
};

/**
 *	public Javascript Class SelectBox
 *
 *	@author		Warwick Bambrook
 *
 */
 
function SelectBox(width,height) {
	this.init(width,height);
}

SelectBox.prototype.init = function (width,height) {
	this._startx = 0;
	this._starty = 0;
	this._endx = 0;
	this._endy = 0;
	this._selectbox = $(document.createElement("div"));
	this._selectbox.setStyle({position: 'absolute',left:0,top:0,width:0,height:0,borderWidth:2
			,borderColor:'darkBlue',backgroundColor:'blue',opacity:0.4,visibility:'hidden' });

	this.aspectRatio = width/height;
	this.showSelectBox;
	this.hideSelectBox;
};

SelectBox.prototype.showSelectBox = function () {
	this._selectbox.setStyle({visibility:'visible'});
};

SelectBox.prototype.hideSelectBox = function () {
	this._selectbox.setStyle({visibility:'hidden'});
};

SelectBox.prototype.draw = function () {
	var bounds = this.getBoxBounds();
	// calculate selectBox width and height
	var boxWidth = bounds.x2-bounds.x1;
	var boxHeight = bounds.y2-bounds.y1;
	var calcWidth = parseInt(boxHeight * this.aspectRatio);
	var calcHeight = parseInt(boxWidth / this.aspectRatio);

	if (calcHeight > boxHeight) {
		if (this._starty < this._endy) {
			//this._selectbox.style.left=bounds.x1;
			//this._selectbox.style.top=bounds.y1;
			//this._selectbox.style.width=boxWidth;
			//this._selectbox.style.height=calcHeight;
			this._selectbox.setStyle({left: bounds.x1, top: bounds.y1, width: boxWidth, height:calcHeight});
		} else {
			var adjustedTop = bounds.y1 - (calcHeight-boxHeight);
			//this._selectbox.style.left=bounds.x1;
			//this._selectbox.style.top=adjustedTop;
			//this._selectbox.style.width=boxWidth;
			//this._selectbox.style.height=calcHeight;
			this._selectbox.setStyle({left: bounds.x1, top: adjustedTop, width: boxWidth, height:calcHeight });
		}
	} else {
		if (this._startx < this._endx) {
			//this._selectbox.style.left=bounds.x1;
			//this._selectbox.style.top=bounds.y1;
			//this._selectbox.style.width=calcWidth;
			//this._selectbox.style.height=boxHeight;
			this._selectbox.setStyle({left: bounds.x1, top: bounds.y1, width: calcWidth, height:boxHeight});
		} else {
			var adjustedLeft = bounds.x1 -(calcWidth-boxWidth);
			//this._selectbox.style.left=adjustedLeft;
			//this._selectbox.style.top=bounds.y1;
			//this._selectbox.style.width=calcWidth;
			//this._selectbox.style.height=boxHeight;
			this._selectbox.setStyle({left: adjustedLeft, top: bounds.y1, width: calcWidth, height:boxHeight});
		}
	}
};

SelectBox.prototype.getBoxBounds = function () {
	var bounds = {};
	if (this._startx < this._endx) {
		bounds.x1 = this._startx;
		bounds.x2 = this._endx;
	} else {
		bounds.x1 = this._endx;
		bounds.x2 = this._startx;
	}
	if (this._starty < this._endy) {
		bounds.y1 = this._starty;
		bounds.y2 = this._endy;
	} else {
		bounds.y1 = this._endy;
		bounds.y2 = this._starty;
	}
	var boxWidth = bounds.x2-bounds.x1;
	var boxHeight = bounds.y2-bounds.y1;
	var calcWidth = parseInt(boxHeight * this.aspectRatio);
	var calcHeight = parseInt(boxWidth / this.aspectRatio);
	if (calcHeight > boxHeight) {
		if (this._starty < this._endy) {
			bounds.y2 = bounds.y1 + calcHeight;
		} else {
			bounds.y1 = bounds.y1 - (calcHeight-boxHeight);
		}
	} else {
		if (this._startx < this._endx) {
			bounds.x2 = bounds.x1 + calcWidth;
		} else {
			bounds.x1 = bounds.x1 -(calcWidth-boxWidth);
		}
	}
	return bounds;
};

/**
 *	public Javascript Class GeoFence
 *
 *	@author		Warwick Bambrook
 *
 */
 
function GeoFence(x,y,geometry) {
	this.init(x,y,geometry);
}

GeoFence.prototype.init = function (x,y,geometry) {
	this._width=parseInt(geometry);
	this._height=parseInt(geometry);
	this._x = x;
	this._y = y;
	this._lng=0;
	this._lat=0;
	this._geometry = '';
	this._geofence = $(document.createElement("div"));
	var pushPin = new Image();
	pushPin.src = '/LVMUI/images/pinRed.gif';
	this._geofence.appendChild(pushPin);
	var xPos = x-(this._width/2);
	var yPos = y-(this._width/2);
//	this._geofence.setStyle({position:'absolute',left:xPos,top:yPos,zIndex:7000
//			,width:this._width,height:this._height,opacity:1.0,visibility:'hidden'});
	this._geofence.style.position='absolute';
	this._geofence.style.left=xPos;
	this._geofence.style.top=yPos;
	this._geofence.style.width=this._width;
	this._geofence.style.height=this._height;
	this._geofence.style.opacity=1.0;
	this._geofence.style.visibility='hidden';
	var canvas = $(document.createElement("div"));
	this._graphics = new jsGraphics(canvas);
	this._geofence.appendChild(canvas);
	this.showGeoFence;
	this.hideGeoFence;
};

GeoFence.prototype.showGeoFence = function () {
	this._geofence.style.visibility='visible';
};

GeoFence.prototype.hideGeoFence = function () {
	this._geofence.style.visibility='hidden';
};

GeoFence.prototype.draw = function() {
	this.showGeoFence();
	this._graphics.clear();
	var left = this._x - 16;
	var top = this._y - 16;
	this._geofence.setStyle({left: left, top: top, width: this._width, height:this._height});
//	this._geofence.style.left=left;
//	this._geofence.style.top=top;
//	this._geofence.style.width=this._width;
//	this._geofence.style.height=this._height;
	this._graphics.setColor("#0000ff"); // blue
	var circleX = (0 - (this._width/2)) + 16;
	var circleY = (0 - (this._height/2)) + 16;
	this._graphics.drawEllipse(circleX, circleY, this._width, this._height);
	this._graphics.paint();
};
