var CMapViewerTransact = Class.create();

Object.extend(Object.extend(CMapViewerTransact.prototype, CTransact.prototype), 
{
	initialize: function(url)
	{
		CTransact.prototype.initialize.call(this);
		this.SetMode(false);
		this.m_url = url;
	    this.m_Class 	= 'CMapViewerTransact';
		this.SetType(c_strTransactFlowType_URL);
	},
	
	GetServiceDispatcherURL: function()
	{
	    return this.m_url;
	},
	
	UpdateImage: function(oViewer, bDirty)
	{
		var oImage = oViewer.m_oCanvas.m_Image;
		var oHolder = oViewer.m_Parent;

		oImage.onload = this.OnImageLoad.bind(this, oViewer, bDirty);
		oImage.onerror = oHolder.TempEnableWindow.bind(oHolder, true);
		oHolder.TempEnableWindow(false);
		oImage.src = this.GetURL();
	},
	
	OnImageLoad: function(oViewer, bDirty)
	{
		var oHolder = oViewer.m_Parent;

		oViewer.m_oCanvas.SetImageObject(oViewer);
		if(bDirty)
			oViewer.UpdateInfos(this);
		oHolder.OnImageLoaded();
	}
});

var CMapViewerCanvas = Class.create();

CMapViewerCanvas.prototype =
{
	m_iZoomStep: 5,
	m_iZoomSpeed: 50,
	m_iMinDelta: 3,
		
	initialize: function()
	{
	    this.m_Class 	= 'CMapViewerCanvas';
	},

	SetCursor: function(strStyle)
	{
		if(this.m_Image && this.m_Image.style)
			this.m_Image.style.cursor = strStyle;
	},
	
	CreateImage: function(element)
	{
		if(element)
		{
			this.m_Image = document.createElement('img');
			this.m_Image.galleryimg = false;		// IE6 only
			this.m_Image.style.position		= 'absolute';
			this.m_Image.border = '0px';
			element.insertBefore(this.m_Image, element.firstChild);
			Event.observe(this.m_Image, 'drag', this.OnDrag);
		}
	},
	
	CreateRect: function(element)
	{
		if(element)
		{
			this.m_rect = document.createElement('div');			
			this.m_rect.style.position		= 'absolute';
			this.m_rect.style.border		= '1px solid #000000';
			this.m_rect.style.background	= '#FFFFFF';
			this.m_rect.style.filter 		= 'alpha(opacity=70)';
			this.m_rect.style.opacity		= '0.7';
			this.m_rect.style.visibility	= 'hidden';
			this.m_rect.style.fontSize		= '0px';
			element.appendChild(this.m_rect);
		}
	},
	
	SetImageObject: function(oViewer)
	{
		if(this.m_Image)
		{
			if(!this.m_iWidth)
				this.m_iWidth = this.m_Image.width;
			if(!this.m_iHeight)
				this.m_iHeight = this.m_Image.height;
			CTools.SetElementPosition(this.m_Image, 0, 0, this.m_iWidth, this.m_iHeight);
			oViewer.ShowWndLayers(true);
		}
	},

	SetImage: function(oViewer, x, y)
	{
		if(this.m_Image)
		{
			oViewer.ShowWndLayers(false);
			CTools.SetElementPosition(this.m_Image, x, y);
		}
	},

	ZoomImage: function(oViewer, x, y, r, callBack)
	{
		if(this.m_Image && this.m_iZoomStep && (r != 1))
		{
			var x0 = this.m_Image.offsetLeft;
			var y0 = this.m_Image.offsetTop;
			var w0 = this.m_Image.offsetWidth;
			var h0 = this.m_Image.offsetHeight;
			var x1 = Math.round(x*(1-r)+x0*r);
			var y1 = Math.round(y*(1-r)+y0*r);

			var dw = w0*(1-r)/this.m_iZoomStep;
			var dh = h0*(1-r)/this.m_iZoomStep;
			var dx = (x0-x1)/this.m_iZoomStep;
			var dy = (y0-y1)/this.m_iZoomStep;
			var i = 1;

			var self = this;
			var callback = function()
			{
				CTools.SetElementPosition(self.m_Image, Math.round(x0-i*dx), Math.round(y0-i*dy), Math.round(w0-i*dw), Math.round(h0-i*dh));
				if(i < self.m_iZoomStep)
				{
					++i;
					setTimeout(callback, self.m_iZoomSpeed);
				}
				else if(callBack)
				{
					callBack();
				}
			}

			oViewer.ShowWndLayers(false);
			callback();
			return [x1, y1, x1+Math.round(w0*r), y1+Math.round(h0*r)];
		}
	},
	
	_checkCoordForZoom: function(xt0, yt0, xt1, yt1)
	{
		var coords;
		if(((xt1-xt0) < this.m_iMinDelta) && ((yt0-yt1) < this.m_iMinDelta))
		{
			var xc = xt0+((xt1-xt0)>>1);
			var yc = yt0+((yt1-yt0)>>1);
			var w0 = this.m_Image.offsetWidth>>2;
			var h0 = this.m_Image.offsetHeight>>2;
			coords = [xc-w0, yc-h0, xc+w0, yc+h0];
		}
		else
			coords = [xt0, yt0, xt1, yt1];		
		return coords;
	},
	
	_zoom: function(oViewer, coords, w0, h0, r)
	{
		var x0 = this.m_Image.offsetLeft;
		var y0 = this.m_Image.offsetTop;
		var x1 = parseInt((w0>>1)-r*(coords[0]+((coords[2]-coords[0])>>1)));
		var y1 = parseInt((h0>>1)-r*(coords[1]+((coords[3]-coords[1])>>1)));
		var dw = w0*(1-r)/this.m_iZoomStep;
		var dh = h0*(1-r)/this.m_iZoomStep;
		var dx = (x0-x1)/this.m_iZoomStep;
		var dy = (y0-y1)/this.m_iZoomStep;
		var i = 1;

		var self = this;
		var callback = function()
		{
			CTools.SetElementPosition(self.m_Image, Math.round(x0-i*dx), Math.round(y0-i*dy), Math.round(w0-i*dw), Math.round(h0-i*dh));
			if(i < self.m_iZoomStep)
			{
				++i;
				setTimeout(callback, self.m_iZoomSpeed);
			}
		}
		oViewer.ShowWndLayers(false);
		callback();
	},
	
	ZoomInImage: function(oViewer, xt0, yt0, xt1, yt1)
	{		
		if(this.m_Image && this.m_iZoomStep)
		{
			var coords = this._checkCoordForZoom(xt0, yt0, xt1, yt1);
			var w0 = this.m_Image.offsetWidth;
			var h0 = this.m_Image.offsetHeight;

			var r = Math.min(w0/(coords[2]-coords[0]), h0/(coords[3]-coords[1]));
			if(r > 1)
			{
				this._zoom(oViewer, coords, w0, h0, r);
			}
			return coords;
		}
	},
	
	ZoomOutImage: function(oViewer, xt0, yt0, xt1, yt1)
	{
		if(this.m_Image && this.m_iZoomStep)
		{
			var coords = this._checkCoordForZoom(xt0, yt0, xt1, yt1);
			var w0 = this.m_Image.offsetWidth;
			var h0 = this.m_Image.offsetHeight;

			var r = Math.max((coords[2]-coords[0])/w0, (coords[3]-coords[1])/h0);
			if(r < 1)
			{
				this._zoom(oViewer, coords, w0, h0, r);
			}
			return coords;
		}
	},

	SetRect: function(x1, y1, x2, y2)
	{
		if(this.m_rect)
		{
			var w0 = Math.abs(x2-x1);
			var h0 = Math.abs(y2-y1);
			if((w0 >= this.m_iMinDelta) || (h0 >= this.m_iMinDelta))
			{
				CTools.SetElementPosition(this.m_rect, Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(y2-y1));
				this.m_rect.style.visibility	= 'visible';
			}
			else
				this.HideRect();
		}
	},
	
	HideRect: function()
	{
		if(this.m_rect)
		{
			CTools.SetElementPosition(this.m_rect, -1, -1, 1, 1);
			this.m_rect.style.visibility	= 'hidden';
		}
	},
	
	OnDrag: function()
	{
		//Return false to prevent ie from dragging object
		return false;
	}	
}

var CMapTooltip = Class.create();

CMapTooltip.prototype =
{
	initialize: function()
	{
	    this.m_Class 	= 'CMapTooltip';
		this.m_bEnable = true;
	},

	Enable: function(bEnable)
	{
		this.m_bEnable = bEnable;
	},
	
	OnMouseMove: function(oViewer)
	{
		if(this.m_bEnable && oViewer)
		{
			if(!this.m_oTooltipCtrl)
			{
				var aTmp = oViewer.GetPosition();

				this.m_iOffsetX = aTmp[0];
				this.m_iOffsetY = aTmp[1];
				this.m_iMaxWidth = aTmp[2];
				this.m_iMaxHeight = aTmp[3];
				this.m_oTooltipCtrl = new CTooltipCtrl(200);				
				this.m_oTooltipCtrl.SetHandler(1, this.OnTimeout.bind(this));
			}

			var vGeoInfos = oViewer.GetInfos();
			if(vGeoInfos)
			{
				var pt = oViewer.GetClientCursorPos();
				var serie;
				var tooltip;
				var bLoop = true;
				
				this.OnMouseOut();
				for(var i = 0; (i < vGeoInfos.length) && bLoop; ++i)
				{
					serie = vGeoInfos[i];
					for(var j = 0; (j < serie.m_aGeoContent.length) && bLoop; ++j)
					{
						tooltip = serie.m_aGeoContent[j];
						if(tooltip.v && (tooltip.x1 <= pt.m_X) && (tooltip.y1 <= pt.m_Y) && (tooltip.x2 >= pt.m_X) && (tooltip.y2 >= pt.m_Y))
						{
							if(this.m_oRect)
								this.SetRect(this.m_oRect, tooltip.x1, tooltip.y1, tooltip.x2-1, tooltip.y2-1);
							this.m_oTooltipCtrl.OnMouseMove([serie, tooltip], 1, Math.min(this.m_iMaxWidth, tooltip.x2) + this.m_iOffsetX, Math.max(0, tooltip.y1) + this.m_iOffsetY, true);
							bLoop = false;
						}
					}
				}
			}
		}
	},

	OnMouseOut: function()
	{
		if(this.m_oTooltipCtrl)
		{
			this.Hide();
			this.m_oTooltipCtrl.OnMouseOut();
		}
	},

	OnTimeout: function(ctrl, aParams)
	{
		if(aParams.length > 1)
		{
			var serie = aParams[0];
			var tooltip = aParams[1];
			var table = document.createElement('table');
			var tr, td, text;

			ctrl.m_ScriptItem.innerHTML = '';		
			for(i = 0; (i < serie.m_aTTColumns.length) && (i < tooltip.v.length); ++i)
			{
				if(serie.m_aTTColumns[i] || tooltip.v[i])
				{
					tr = table.insertRow(-1);
					td = tr.insertCell(-1);
					if(serie.m_aTTColumns[i] && tooltip.v[i])
					{
						text = document.createTextNode(unescape(serie.m_aTTColumns[i]));
						td.appendChild(text);
						td.style.fontWeight = 'bold';
						td = tr.insertCell(-1);
						td.style.textAlign = 'right';
						text = document.createTextNode(unescape(tooltip.v[i]));
					}
					else
					{
						td.colSpan = 2;
						if(serie.m_aTTColumns[i])
						{
							td.style.fontWeight = 'bold';
							text = document.createTextNode(unescape(serie.m_aTTColumns[i]));
						}
						else
							text = document.createTextNode(unescape(tooltip.v[i]));
					}
					td.appendChild(text);
				}
			}
			ctrl.m_ScriptItem.appendChild(table);
		}
	},
	
	CreateRect: !(window.attachEvent && !window.opera)?function(element)
	{
		// other browser
		var obj = [
					document.createElement('div'),
					document.createElement('div'),
					document.createElement('div'),
					document.createElement('div')
				];

		for(i = 0; i < obj.length; ++i)
		{
			obj[i].style.position = 'absolute';
			obj[i].style.visibility = 'hidden';
			obj[i].style.backgroundColor = '#000000';
			element.appendChild(obj[i]);
		}
		obj[0].style.width = '1px';
		obj[1].style.height = '1px';
		obj[2].style.width = '1px';
		obj[3].style.height = '1px';
		this.m_oRect = obj;
	}:function(element)
	{
		// IE
		this.m_oRect = document.createElement('div');
		this.m_oRect.style.border = '1px solid black';
		this.m_oRect.style.position = 'absolute';
		this.m_oRect.style.visibility = 'hidden';
		element.insertBefore(this.m_oRect, element.firstChild);
	},
	
	SetRect: !(window.attachEvent && !window.opera)?function(obj, x1, y1, x2, y2)
	{
		// other browser
		for(i = 0; i < obj.length; ++i)
			obj[i].style.visibility = 'visible';
		obj[0].style.left = obj[1].style.left = obj[3].style.left = x1 + 'px';
		obj[0].style.top = obj[1].style.top = obj[2].style.top = y1 + 'px';
		obj[2].style.left = x2 + 'px';
		obj[3].style.top = y2 + 'px';
		
		obj[0].style.height = obj[2].style.height = (y2 - y1) + 'px';
		obj[1].style.width = obj[3].style.width = (x2 - x1 + 1) + 'px';
	}:function(obj, x1, y1, x2, y2)
	{
		// IE
		obj.style.visibility = 'visible';
		obj.style.left = x1 + 'px';
		obj.style.top = y1 + 'px';
		obj.style.height = (y2 - y1) + 'px';
		obj.style.width = (x2 - x1) + 'px';
	},

	Hide: !(window.attachEvent && !window.opera)?function()
	{
		// other browser
		if(this.m_oRect)
		{
			for(i = 0; i < this.m_oRect.length; ++i)
			{
				this.m_oRect[i].style.visibility = 'hidden';
			}
		}
	}:function()
	{
		// IE
		if(this.m_oRect)
			this.m_oRect.style.visibility = 'hidden';
	}	
}

var CMapLayer = Class.create();

Object.extend(Object.extend(CMapLayer.prototype, CWindow.prototype), 
{
	initialize: function(name, ID, Parentwnd, Width, Height)
	{
		CWindow.prototype.initialize.call(this, name, ID, Parentwnd, Width, Height);
	    this.m_Class 	= 'CMapLayer';
	},
			
	OnEndCreate: function()
	{
		this.m_ScriptItem.style.border = 'none';
	}
});

var CMapViewer = Class.create();

Object.extend(Object.extend(CMapViewer.prototype, CWindow.prototype), 
{
	m_iMouseWheelCallDelay: 1000,

	initialize: function(name, ID, Parentwnd, Width, Height)
	{
		CWindow.prototype.initialize.call(this, name, ID, Parentwnd, Width, Height);
	    this.m_Class 	= 'CMapViewer';
		this.m_oCanvas = new CMapViewerCanvas('', 'canvas', this);

		this.m_oTooltips = new CMapTooltip();
		
		this.m_oWnd = new CMapLayer('', 'ModeLayer', this);
		this.m_oWnd.SetPosition(0, 0, 0, 0);
		this.m_oWnd.ShowWindow = function(bShow) {	if(this.m_ScriptItem) this.m_ScriptItem.style.visibility = bShow?'visible':'hidden';}
				
		this.m_oMode = new CMode();
		this.m_iWheelZoom = 0;
		this.m_bHideTooltip = false;
		this.m_bWheelZoomMoved = false;
	},

	_sortPred: function(a, b)
	{
		var surfa = Math.abs(a.x2-a.x1)*Math.abs(a.y2-a.y1);
		var surfb = Math.abs(b.x2-b.x1)*Math.abs(b.y2-b.y1);;
		if(surfa < surfb) return -1;
		if(surfa > surfb) return 1;
		return 0;
	},

	EnableToolTips: function(bEnable)
	{
		// To be completed...
		this.m_oTooltips.Enable(bEnable);
	},

	CreateWndLayer: function()
	{
		var wnd = new CMapLayer('', '', this.m_oWnd, 0, 0);
		wnd.SetPosition(0, 0, 0, 0);
		if(this.m_ScriptItem)
			wnd.Create();
		return wnd;
	},
	
	ShowWndLayers: function(bShow)
	{
		this.m_oWnd.ShowWindow(bShow);
	},
	
	GetPosition: function()
	{
		var pt = this.GetControlPosition(this.m_ScriptItem);
		return [pt.m_X, pt.m_Y, this.m_Width, this.m_Height];
	},

	UpdateInfos: function(transact)
	{
		transact.ClearParams();
		transact.AddParam('a', 'tooltips');
		try
		{
			this.m_vGeoInfos = eval(transact.Call().transport.responseText);
			for(var i = 0; i < this.m_vGeoInfos.length; ++i)
			{
				if(this.m_vGeoInfos[i].m_aTTColumns)
					this.m_vGeoInfos[i].m_aGeoContent.sort(this._sortPred);
			}
		}
		catch(e) 
		{
			delete this.m_vGeoInfos;
		}
	},
	
	GetInfos: function()
	{
		return this.m_vGeoInfos;
	},
	
	OnEndCreate: function()
	{
		if(this.m_ScriptItem)
		{
			var transact = this.GetTransact();
			this.m_ScriptItem.style.overflow = 'hidden';
			this.m_ScriptItem.style.backgroundColor = '#A0A0A0';
			this.m_oTooltips.CreateRect(this.m_ScriptItem);
			this.m_oCanvas.CreateImage(this.m_ScriptItem);
			this.m_oCanvas.SetCursor(this.m_oMode.m_cursor);
			this.m_oCanvas.CreateRect(this.m_ScriptItem);
			this.RefreshMap(true);
		}
	},
	
	UpdateImage: function(bDirty)
	{
		var transact = this.GetTransact();
		if(this.m_Width)
			transact.AddParam('w', this.m_Width);
		if(this.m_Height)
			transact.AddParam('h', this.m_Height);
		transact.UpdateImage(this, bDirty);
	},

	GetTransact: function()
	{
		return this.m_Parent.GetTransact();
	},
	
	SetMode: function(oMode)
	{
		this.m_oMode = oMode;
		this.m_oCanvas.SetCursor(oMode.m_cursor);
	},
	
	OnMouseWheel: function(pPoint, lDelta)
	{
		var x1, y1, x2, y2;
		var self = this;		
		var callBack = function()
		{
			if(self.m_bWheelZoomMoved || self.m_iWheelZoom)
			{
				self.m_iZoomCall = setTimeout(
					function() 
					{
						var transact = self.GetTransact();
						
						transact.ClearParams();
						transact.AddParam('a', 'zoomout');
						transact.AddParam('x1', x1);
						transact.AddParam('x2', x2);
						transact.AddParam('y1', y1);
						transact.AddParam('y2', y2);
						self.UpdateImage(true);
						self.m_iWheelZoom = 0;
						self.m_bWheelZoomMoved = false;
					}, 
					self.m_iMouseWheelCallDelay);
			}
			else
				self.ShowWndLayers(true);
			self.m_Parent.TempEnableWindow(true);
		}

		if(this.m_iZoomCall)
			clearTimeout(this.m_iZoomCall);
		this.m_Parent.TempEnableWindow(false);
		if(!this.m_bWheelZoomMoved)
		{
		 	if(!this.m_iWheelZoom)
		 		this.m_currentPt = pPoint;
		 	else
				this.m_bWheelZoomMoved = ((pPoint.m_X != this.m_currentPt.m_X) || (pPoint.m_Y != this.m_currentPt.m_Y));
			this.m_iWheelZoom += lDelta;
		}
		var coords = this.m_oCanvas.ZoomImage(this, pPoint.m_X, pPoint.m_Y, (lDelta > 0)?2:0.5, callBack);
		x1 = coords[0];
		y1 = coords[1];
		x2 = coords[2];
		y2 = coords[3];
	},

	OnMouseClick: function()
	{
		if(this.m_oMode)
			this.m_oMode.OnMouseClick(this, this.m_oCanvas, this.GetClientCursorPos());
	},

	OnMouseMove: function()
	{
		if(this.m_oMode)
			this.m_oMode.OnMouseMove(this, this.m_oCanvas, this.GetClientCursorPos());
		if(!this.m_bHideTooltip && this.m_oTooltips)
			this.m_oTooltips.OnMouseMove(this);
	},
	
	OnLButtonDown: function()
	{
		//This is to prevent ff from dragging object
		if (this.m_CurrentEvent && this.m_CurrentEvent.preventDefault)
			this.m_CurrentEvent.preventDefault()
		if(this.m_oMode)
			this.m_oMode.OnLButtonDown(this, this.m_oCanvas, this.GetClientCursorPos());
		if(this.m_oTooltips)
		{
			this.m_oTooltips.OnMouseOut();
			this.m_bHideTooltip = true;
		}
	},

	OnMouseOut: function()
	{
		if(this.m_oTooltips)
			this.m_oTooltips.OnMouseOut();
	},

	OnLButtonUp: function()
	{
		if(this.m_oMode)
			this.m_oMode.OnLButtonUp(this, this.m_oCanvas, this.GetClientCursorPos());
		this.m_bHideTooltip = false;
	},
	
	RefreshMap: function(bDirty)
	{
		var transact = this.GetTransact();

		transact.ClearParams();
		transact.AddParam('a', 'getimg');
		this.UpdateImage(bDirty);
	},
	
	LoadToolTips: function()
	{
		this.UpdateInfos(this.GetTransact());
	}
});

var CMode = Class.create();

CMode.prototype = 
{
	m_cursor: 'default',
	
	m_oOptions: {},
	
	initialize: function()
	{
		this.m_pClickedPoint = new CPoint();
	    this.m_Class = 'CMode';
	},
	
	OnMouseClick: function(oViewer, canvas, pt)
	{
	},

	OnMouseMove: function(oViewer, canvas, pt)
	{
	},
	
	OnLButtonDown: function(oViewer, canvas, pt)
	{
	},

	OnLButtonUp: function(oViewer, canvas, pt)
	{
	},

	OnImageLoaded: function(oViewer, canvas)
	{
	},
	
	GetButton: function() {	return this.m_oOptions;	}
}

var CZoomPlusMode = Class.create();

Object.extend(Object.extend(CZoomPlusMode.prototype, CMode.prototype), 
{
	m_cursor: 'crosshair',

	m_oOptions:
	{
		id: 'zoomin', 
		dflt: '/AGI.WebClient/images/zoomplus_up.jpg', 
		dfltTooltip: 'Zoom In', 
		selected: '/AGI.WebClient/images/zoomplus_down.jpg', 
		focus: '/AGI.WebClient/images/zoomplus_focus.jpg', 
		disabled: '/AGI.WebClient/images/zoomplus_grayed.jpg'
	},
	
	initialize: function()
	{
		CMode.prototype.initialize.call(this);
	    this.m_Class 	= 'CZoomPlusMode';
	    this.m_bButtonDown = false;
	},
	
	OnMouseMove: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			canvas.SetRect(this.m_pClickedPoint.m_X, this.m_pClickedPoint.m_Y, pt.m_X, pt.m_Y);
		}
	},

	OnLButtonDown: function(oViewer, canvas, pt)
	{
		if(canvas)
		{
			if(this.m_bButtonDown)
			{
				this.OnLButtonUp(oViewer, canvas, pt);
			}
			else
			{
				this.m_bButtonDown = true;
				this.m_pClickedPoint = pt;
				canvas.SetRect(pt.m_X, pt.m_Y, pt.m_X, pt.m_Y);
			}
		}
	},

	OnLButtonUp: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			var transact = oViewer.GetTransact();			
			var coords = canvas.ZoomInImage(oViewer, Math.min(pt.m_X, this.m_pClickedPoint.m_X), Math.min(pt.m_Y, this.m_pClickedPoint.m_Y), Math.max(pt.m_X, this.m_pClickedPoint.m_X), Math.max(pt.m_Y, this.m_pClickedPoint.m_Y));
			canvas.HideRect();
			this.m_bButtonDown = false;
			
			if(coords)
			{
				transact.ClearParams();
				transact.AddParam('x1', coords[0]);
				transact.AddParam('x2', coords[2]);
				transact.AddParam('y1', coords[1]);
				transact.AddParam('y2', coords[3]);
				transact.AddParam('a', this.m_oOptions.id);
				oViewer.UpdateImage(true);
			}
		}
	}
});

var CZoomMinusMode = Class.create();

Object.extend(Object.extend(CZoomMinusMode.prototype, CMode.prototype), 
{
	m_cursor: 'crosshair',
	
	m_oOptions:
	{
		id: 'zoomout', 
		dflt: '/AGI.WebClient/images/zoomminus_up.jpg', 
		dfltTooltip: 'Zoom Out', 
		selected: '/AGI.WebClient/images/zoomminus_down.jpg', 
		focus: '/AGI.WebClient/images/zoomminus_focus.jpg', 
		disabled: '/AGI.WebClient/images/zoomminus_grayed.jpg'
	},

	initialize: function()
	{
		CMode.prototype.initialize.call(this);
	    this.m_Class 	= 'CZoomMinusMode';
	    this.m_bButtonDown = false;
	},
	
	OnMouseMove: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			canvas.SetRect(this.m_pClickedPoint.m_X, this.m_pClickedPoint.m_Y, pt.m_X, pt.m_Y);
		}
	},

	OnLButtonDown: function(oViewer, canvas, pt)
	{
		if(canvas)
		{
			if(this.m_bButtonDown)
			{
				this.OnLButtonUp(oViewer, canvas, pt);
			}
			else
			{
				this.m_bButtonDown = true;
				this.m_pClickedPoint = pt;
				canvas.SetRect(pt.m_X, pt.m_Y, pt.m_X, pt.m_Y);
			}
		}
	},

	OnLButtonUp: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			var transact = oViewer.GetTransact();
			var coords = canvas.ZoomOutImage(oViewer, Math.min(pt.m_X, this.m_pClickedPoint.m_X), Math.min(pt.m_Y, this.m_pClickedPoint.m_Y), Math.max(pt.m_X, this.m_pClickedPoint.m_X), Math.max(pt.m_Y, this.m_pClickedPoint.m_Y));
			canvas.HideRect();
			this.m_bButtonDown = false;

			if(coords)
			{
				transact.ClearParams();
				transact.AddParam('x1', coords[0]);
				transact.AddParam('x2', coords[2]);
				transact.AddParam('y1', coords[1]);
				transact.AddParam('y2', coords[3]);
				transact.AddParam('a', this.m_oOptions.id);
				oViewer.UpdateImage(true);
			}
		}
	}
});

var CMoveMode = Class.create();

Object.extend(Object.extend(CMoveMode.prototype, CMode.prototype), 
{
	m_cursor: 'move',
	
	m_oOptions:
	{
		id: 'pan', 
		dflt: '/AGI.WebClient/images/pan_up.jpg', 
		dfltTooltip: 'Pan', 
		selected: '/AGI.WebClient/images/pan_down.jpg', 
		focus: '/AGI.WebClient/images/pan_focus.jpg', 
		disabled: '/AGI.WebClient/images/pan_grayed.jpg'
	},
	
	initialize: function()
	{
		CMode.prototype.initialize.call(this);
	    this.m_Class 	= 'CMoveMode';
	    this.m_bButtonDown = false;
	},
	
	OnMouseMove: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			canvas.SetImage(oViewer, pt.m_X - this.m_pClickedPoint.m_X, pt.m_Y - this.m_pClickedPoint.m_Y);
		}
	},

	OnLButtonDown: function(oViewer, canvas, pt)
	{
		if(canvas)
		{
			if(this.m_bButtonDown)
			{
				this.OnLButtonUp(oViewer, canvas, pt);
			}
			else
			{
				this.m_bButtonDown = true;
				this.m_pClickedPoint = pt;
			}
		}
	},

	OnLButtonUp: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			var transact = oViewer.GetTransact();

			this.m_bButtonDown = false;
			canvas.SetImage(oViewer, pt.m_X - this.m_pClickedPoint.m_X, pt.m_Y - this.m_pClickedPoint.m_Y);
	
			transact.ClearParams();
			transact.AddParam('x1', this.m_pClickedPoint.m_X);
			transact.AddParam('x2', pt.m_X);
			transact.AddParam('y1', this.m_pClickedPoint.m_Y);
			transact.AddParam('y2', pt.m_Y);
			transact.AddParam('a', this.m_oOptions.id);
			oViewer.UpdateImage(true);
		}
	}
});

var CSelectMode = Class.create();

Object.extend(Object.extend(CSelectMode.prototype, CMode.prototype), 
{
	m_cursor: 'default',
	
	m_oOptions:
	{
		id: 'select', 
		dfltTooltip: 'Select', 
		dflt: '/AGI.WebClient/images/select_up.jpg', 
		selected: '/AGI.WebClient/images/select_down.jpg', 
		focus: '/AGI.WebClient/images/select_focus.jpg', 
		disabled: '/AGI.WebClient/images/select_grayed.jpg'
	},

	initialize: function()
	{
		CMode.prototype.initialize.call(this);
	    this.m_Class 	= 'CSelectMode';
	    this.m_bButtonDown = false;
	},
	
	OnMouseMove: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			canvas.SetRect(this.m_pClickedPoint.m_X, this.m_pClickedPoint.m_Y, pt.m_X, pt.m_Y);
		}
	},

	OnLButtonDown: function(oViewer, canvas, pt)
	{
		if(canvas)
		{
			if(this.m_bButtonDown)
			{
				this.OnLButtonUp(oViewer, canvas, pt);
			}
			else
			{
				this.m_bButtonDown = true;
				this.m_pClickedPoint = pt;
				canvas.SetRect(pt.m_X, pt.m_Y, pt.m_X, pt.m_Y);
			}
		}
	},

	OnLButtonUp: function(oViewer, canvas, pt)
	{
		if(canvas && this.m_bButtonDown)
		{
			this.OnSelectComplete(oViewer, canvas, this.m_pClickedPoint, pt);
			this.m_bButtonDown = false;
			canvas.HideRect();
		}
	},

	OnSelectComplete: function(oViewer, canvas, pt0, pt1)
	{
	}
});

var CMapHolder = Class.create();

CMapHolder.HB_PAN		= 0x00000001;
CMapHolder.HB_SELECT 	= 0x00000010;
CMapHolder.HB_ZOOMPLUS 	= 0x00000100;
CMapHolder.HB_ZOOMMINUS = 0x00001000;
CMapHolder.HB_SMARTZOOM = 0x00010000;
CMapHolder.HB_HDTOOLTIP = 0x00100000;

Object.extend(Object.extend(CMapHolder.prototype, CWindow.prototype), 
{
	m_oSmartZoomDesc: 
	{
		id: 'smartzoom', 
		dfltTooltip: 'Original Zoom', 
		dflt: '/AGI.WebClient/images/smartzoom_up.jpg', 
		selected: '/AGI.WebClient/images/smartzoom_down.jpg', 
		focus: '/AGI.WebClient/images/smartzoom_focus.jpg', 
		disabled: '/AGI.WebClient/images/smartzoom_grayed.jpg',
		handler: function(oViewer, oButton, oTransact, oCanvas)
		{	
			oTransact.ClearParams();
			oTransact.AddParam('a', oButton.m_ID);
			oViewer.UpdateImage(true);
		}
	},
	
	m_oTooltipDesc: 
	{
		id: 'tooltip', 
		dfltTooltip: 'Show/Hide Tooltips', 
		dflt: '/AGI.WebClient/images/tooltip_up.jpg', 
		selected: '/AGI.WebClient/images/tooltip_down.jpg', 
		focus: '/AGI.WebClient/images/tooltip_focus.jpg', 
		disabled: '/AGI.WebClient/images/tooltip_grayed.jpg',
		handler: function(oViewer, oButton, oTransact, oCanvas)
		{	
			oViewer.EnableToolTips(oButton.GetCheck());
		}
	},
	
	m_oGlobalContext: this,
	
	initialize: function(name, ID, Parentwnd, Width, Height, btMask, url, urlParams)
	{
		var iState = CButton.BSTT_DOWN;
		
		CWindow.prototype.initialize.call(this, name, ID, Parentwnd, Width, Height);
	    this.m_Class 	= 'CMapHolder';
	    this.m_oViewer = new CMapViewer('', 'viewer', this, Width, Height);
		this.m_oViewer.EnableToolTips(true);
		this.m_oToolbar = new CToolBar('', 'toolbar', this);
		this.m_oModeCtnr = {};
		this.m_oCallBacks = {};
		this.m_oTransact = new CMapViewerTransact(url);
		this.m_oTransact.SetSessionId(urlParams);
		
		if(btMask & CMapHolder.HB_PAN)
		{
			this.AddMode(new CMoveMode(), iState);
			iState = CButton.BSTT_UP;
		}
		if(btMask & CMapHolder.HB_SELECT)
		{
			this.AddMode(new CSelectMode(), iState);
			iState = CButton.BSTT_UP;
		}
		if(btMask & CMapHolder.HB_ZOOMPLUS)
		{
			this.AddMode(new CZoomPlusMode(), iState);
			iState = CButton.BSTT_UP;
		}			
		if(btMask & CMapHolder.HB_ZOOMMINUS)
		{
			this.AddMode(new CZoomMinusMode(), iState);
			iState = CButton.BSTT_UP;
		}
		if(btMask & CMapHolder.HB_SMARTZOOM)
		{
			var smart = this.m_oSmartZoomDesc;
			this.AddButton(smart.id, smart.dflt, smart.handler, CButton.BS_PUSHBUTTON, smart.selected, smart.disabled, smart.focus, smart.dfltTooltip);
		}
		if(btMask & CMapHolder.HB_HDTOOLTIP)
		{
			var tt = this.m_oTooltipDesc;
			var btn = this.AddButton(tt.id, tt.dflt, tt.handler, CButton.BS_CHECKBOX, tt.selected, tt.disabled, tt.focus, tt.dfltTooltip);
			btn.SetState(CButton.BSTT_DOWN);
		}
		this.TempEnableWindow(false);
	},
	
	OnEndCreate: function()
	{
		// Tool bar positioned at viewer bottom
		var iHeight = this.m_Height||this.m_oToolbar.m_Height;
		this.m_oViewer.SetPosition(0, 0, this.m_Width||this.m_oToolbar.m_Width, iHeight);
		this.m_oToolbar.SetPosition(0, iHeight - this.m_oToolbar.m_Height);
	},
	
	GetTransact: function()
	{
		return this.m_oTransact;
	},
	
	AddButton: function(id, strRsceUrl, callBack, iStyle, strRsceSelUrl, strRsceDisabledUrl, strRsceFocusUrl, toolTip)
	{
		var oRet;
		
		if(id && strRsceUrl)
		{
			oRet = new CBitmapButton('', id, this.m_oToolbar, 0, 0, strRsceUrl, '', iStyle, strRsceSelUrl, strRsceDisabledUrl, strRsceFocusUrl);
			if(callBack && !this.m_oCallBacks[id])
			{
				this.m_oCallBacks[id] = callBack.bind(this.m_oGlobalContext, this.m_oViewer, oRet);
				if(toolTip)
					this.m_oToolbar.SetTooltip(toolTip, oRet);
			}
		}
		return oRet;
	},

	AddMode: function(oMode, iState)
	{
		if(oMode && oMode.GetButton)
		{
			var buttonImgs = oMode.GetButton();
			if(buttonImgs && buttonImgs.id && buttonImgs.dflt && !this.m_oModeCtnr[buttonImgs.id])
			{
				var button = new CBitmapButton('', buttonImgs.id, this.m_oToolbar, 0, 0, buttonImgs.dflt, '', CButton.BS_RADIO, buttonImgs.selected, buttonImgs.disabled, buttonImgs.focus);
				button.SetState(iState||CButton.BSTT_UP);
				if(iState == CButton.BSTT_DOWN)
				{
					this.m_oViewer.SetMode(oMode);
				}
				this.m_oModeCtnr[button.m_ID] = oMode;
				this.m_oToolbar.Register('mode', button);
				if(buttonImgs.dfltTooltip)
					this.m_oToolbar.SetTooltip(buttonImgs.dfltTooltip, button);
			}
		}
	},
	
	CreateWndLayer: function()
	{
		if(this.m_oViewer) return this.m_oViewer.CreateWndLayer();
	},
	
	OnButtonClick: function(id)
	{
		if(id)
		{
			if(this.m_oModeCtnr[id])
				this.m_oViewer.SetMode(this.m_oModeCtnr[id]);
			else if(this.m_oCallBacks[id] && this.m_oViewer)
				this.m_oCallBacks[id](this.m_oTransact, this.m_oViewer.m_oCanvas);
		}
	},
	
	OnImageLoaded: function()
	{
		if(!this.m_Width || !this.m_Height)
		{
			this.m_Width = this.m_Width||this.m_oViewer.m_oCanvas.m_iWidth;
			this.m_Height = this.m_Height||this.m_oViewer.m_oCanvas.m_iHeight;
			this.OnEndCreate();
		}
		this.TempEnableWindow(true);
		for(property in this.m_oModeCtnr)
		{
			if(this.m_oModeCtnr[property].OnImageLoaded)
				this.m_oModeCtnr[property].OnImageLoaded(this.m_oViewer, this.m_oViewer.m_oCanvas);
		}
	},
	
	EnableToolTips: function(bEnable)
	{
		if(this.m_oViewer)
			this.m_oViewer.EnableToolTips(bEnable);
	}
});

