SIX.Tool.Measure = function (parent, sImage, sToolTip, params)
{
	SIX.Tool.call(this, parent, SIX.eToolTypes.EXCLUSIVE, sImage, sToolTip, params);
	
	var toolData = {aPoints : null, 
						aPixelsX : null,
						aPixelsY : null,
						nSelectedIndex : -1,
						controlLayerName : SIX.Uid.getUid("MeasureTool"),
						mapContainer : null,
						resultContainer : null, 
						elemTotalDistance : null, 
						elemLastSegmentDistance : null, 
						init : function (map) {
							var control = document[map.uid];
							this.aPoints = new Array();
							this.aPixelsX = new Array();
							this.aPixelsY = new Array();
							
							if (this.elemTotalDistance)
								this.elemTotalDistance.innerHTML = "0.00 m";
								
							if (this.elemLastSegmentDistance)
								this.elemLastSegmentDistance.innerHTML = "0.00 m";								
															
							if (SIX.App.bDHTMLControl)
							{
								var canvas = map.getCanvas();
								var ctx = canvas.getContext("2d");
								ctx.clearRect(0, 0, canvas.width, canvas.height);
							}
							else
							{
								var nLayerIndex = control.GetLayerIndex(this.controlLayerName);
								if (nLayerIndex >= 0)
									map.setLayerParameter(this.controlLayerName,"filledcircle1=;polyline1=");
								else 
									nLayerIndex = map.addLayer("SIMPLEVECTOR", "", this.controlLayerName,"color=#ffff00;linewidth=1");						
							}		
						},
						update : function (map, bRecalcPixels) {
							var dDistance = 0.0;
							var dLastSegmentDistance = 0.0;
							for (var i=0; i<this.aPoints.length; i++)
							{
								var point = this.aPoints[i];
								if ((i + 1) < this.aPoints.length)
								{
									var point2 = this.aPoints[i+1];
									dLastSegmentDistance = map.getDistanceBetweenCoords(point.x, point.y, point2.x, point2.y);
									dDistance += dLastSegmentDistance;
								}
							}
			
							if (SIX.App.bDHTMLControl)
							{	
								if (bRecalcPixels)
								{
									for (var i=0; i<this.aPoints.length; i++)
									{
										var point = this.aPoints[i];
										var aPixel = map.getPixelFromEN(point.x, point.y);
										this.aPixelsX[i] = aPixel[0];
										this.aPixelsY[i] = aPixel[1];	
									}
								}							
								if (this.aPixelsX.length && this.aPixelsY.length)
								{
									var canvas = map.getCanvas();
									var ctx = canvas.getContext("2d");
									ctx.clearRect(0, 0, canvas.width, canvas.height);
									ctx.beginPath();
									ctx.moveTo(this.aPixelsX[0], this.aPixelsY[0]);

									for (var i = 0; i < this.aPoints.length; i++)
										ctx.lineTo(this.aPixelsX[i], this.aPixelsY[i]);

									ctx.strokeStyle = "rgb(255,255,0)";
									ctx.stroke();
								}						
							}
							else
							{				
								if (this.aPoints.length == 1)
								{
									var params = "linewidth=10;polyline1=;filledcircle1=" + this.aPoints[0].x + "," + this.aPoints[0].y + "|" +
																			(this.aPoints[0].x + 1) + "," + (this.aPoints[0].y + 1);
								}
								else if (this.aPoints.length > 1)
								{
									var params = "linewidth=1;filledcircle1=;polyline1=";	
									for (var i=0; i<this.aPoints.length; i++)
										params += (i > 0 ? "|" : "") + this.aPoints[i].x + "," + this.aPoints[i].y;
								}
								else
								{
									var params = "filledcircle1=;polyline1=";
								}
							
								map.setLayerParameter(this.controlLayerName, params);
							}

							var getFormattedDistance = function (dDistance)
							{
								if (dDistance >= 1000)
									var sDistance = (dDistance / 1000).toFixed(2) + " km";
								else
									var sDistance = dDistance.toFixed(2) + " m";
								return sDistance;	
							}
							
							if (this.elemTotalDistance)
								this.elemTotalDistance.innerHTML = getFormattedDistance(dDistance);
								
							if (this.elemLastSegmentDistance)
								this.elemLastSegmentDistance.innerHTML = getFormattedDistance(dLastSegmentDistance);														
						}};				
						
	this.addCallback(SIX.eToolCallbacks.ONACTIVATE, 
				function (map, data) {
					map.setPointerMode(PM_POINTER);		
					
					var elemContainer = map.getContainer();
					if (elemContainer && data.mapContainer == elemContainer)	
					{				
						var elemResultContainer = data.resultContainer;
						elemResultContainer.style.display = "block";
					}
					else
					{
						var sDeleteTooltip = "Delete point (Ctrl+click or right mouse button over point to delete)";
						var sDeleteAllTooltip = "Delete all points (Shift+click)";
						var sShowAdvancedTooltip = "Show advanced measurement options.";
						var sHideAdvancedTooltip = "Hide advanced measurement options.";
						
						if (data.mapContainer)
							data.mapContainer.removeChild(data.resultContainer);
						var elemResultContainer = document.createElement("div");
						elemResultContainer.setAttribute("class", "measureContainer");
						elemResultContainer.setAttribute("className", "measureContainer");		
		
						var elemImageDelete = document.createElement("img");	
						elemImageDelete.setAttribute("class", "measureButton");
						elemImageDelete.setAttribute("className", "measureButton");
						elemImageDelete.setAttribute("alt", sDeleteTooltip);
						elemImageDelete.setAttribute("title", sDeleteTooltip);
						elemImageDelete.setAttribute("src", "images/deletePoint.gif");						
						
						elemImageDelete.onmouseover = function()
						{
							this.src = "images/deletePoint_on.gif";
						}
	
						elemImageDelete.onmouseout = function()
						{
							this.src = "images/deletePoint.gif";
						}	
							
						elemImageDelete.onclick = function()
						{
							with ({map : map, data : data})
							{
								map.setPointerMode(PM_POINTER);
								if (data.aPoints.length)
								{
									var nIndex = data.aPoints.length - 1;//Delete last point
									data.aPoints.splice(nIndex, 1);
									data.aPixelsX.splice(nIndex, 1);
									data.aPixelsY.splice(nIndex, 1);
									data.update(map);
								}									
							}
						}
						elemResultContainer.appendChild(elemImageDelete);	
						
						var elemImageDeleteAll = document.createElement("img");		
						elemImageDeleteAll.setAttribute("class", "measureButton");
						elemImageDeleteAll.setAttribute("className", "measureButton");	
						elemImageDeleteAll.setAttribute("alt", sDeleteAllTooltip);
						elemImageDeleteAll.setAttribute("title", sDeleteAllTooltip);
						elemImageDeleteAll.setAttribute("src", "images/deleteAllPoints.gif");						
	
						elemImageDeleteAll.onmouseover = function()
						{
							this.src = "images/deleteAllPoints_on.gif";
						}
	
						elemImageDeleteAll.onmouseout = function()
						{
							this.src = "images/deleteAllPoints.gif";
						}	
						
						elemImageDeleteAll.onclick = function()
						{
							with ({map : map, data : data})
							{
								map.setPointerMode(PM_POINTER);
								data.init(map);								
							}
						}
						elemResultContainer.appendChild(elemImageDeleteAll);

						var elemResultLabel = document.createElement("span");
						elemResultLabel.setAttribute("class", "measureLabel");
						elemResultLabel.setAttribute("className", "measureLabel");
						elemResultLabel.appendChild(document.createTextNode("Total distance:"));
						elemResultContainer.appendChild(elemResultLabel);
	
						var elemResult = document.createElement("span");
						elemResult.setAttribute("class", "measureResult");
						elemResult.setAttribute("className", "measureResult");
						elemResult.appendChild(document.createTextNode(""));
						elemResultContainer.appendChild(elemResult);
	
						var elemLastSegmentLabel = document.createElement("span");
						elemLastSegmentLabel.setAttribute("class", "measureLabel");
						elemLastSegmentLabel.setAttribute("className", "measureLabel");
						elemLastSegmentLabel.appendChild(document.createTextNode("Last segment distance:"));
						elemResultContainer.appendChild(elemLastSegmentLabel);
	
						var elemLastSegment = document.createElement("span");
						elemLastSegment.setAttribute("class", "measureResult");
						elemLastSegment.setAttribute("className", "measureResult");
						elemLastSegment.appendChild(document.createTextNode(""));
						elemResultContainer.appendChild(elemLastSegment);	
						
						elemContainer.appendChild(elemResultContainer);
						
						data.mapContainer = elemContainer;
						data.resultContainer = elemResultContainer;
						data.elemTotalDistance = elemResult;
						data.elemLastSegmentDistance = elemLastSegment;
					}
					data.init(map);
				}, toolData);	

	this.addCallback(SIX.eToolCallbacks.ONDEACTIVATE, 
				function (map, data) {
					var control = document[map.uid];	
				
					if (SIX.App.bDHTMLControl)
					{
						var canvas = map.getCanvas();
						var ctx = canvas.getContext("2d");
						ctx.clearRect(0, 0, canvas.width, canvas.height);
					}
					else
					{
						var nLayerIndex = control.GetLayerIndex(data.controlLayerName);
						if (nLayerIndex >= 0)
							map.setLayerParameter(data.controlLayerName,"filledcircle1=;polyline1=");				
					}
					
					var elemContainer = map.getContainer();
					if (elemContainer && data.mapContainer == elemContainer)	
					{				
						var elemResultContainer = data.resultContainer;
						elemResultContainer.style.display = "none";
					}

				}, toolData);	
				
	this.addCallback(SIX.eToolCallbacks.ONMAPMOUSEDOWN, 
				function (map, data) {
					var bDeleteAllPoints = (map.nMouseMask & MVK_SHIFT);
					if (bDeleteAllPoints)
					{
						data.init(map);
					}
					else
					{					
						var bDeletePoint = (map.nMouseMask & MVK_CONTROL) || (map.nMouseMask & MVK_RBUTTON);
						var nIndex = bDeletePoint ? data.aPoints.length - 1 : data.aPoints.length;
						var bMovePoint = false;			
						var dThreshold = 0.01 * Math.pow(Math.pow((map.brx - map.tlx),2) + Math.pow((map.tly - map.bry),2), 0.5);

						var nearestPoint = SIX.Util.getNearestPoint(map.dMouseWorldX, map.dMouseWorldY, data.aPoints);
						var nNearestPointIndex = nearestPoint ? nearestPoint[0] : -1;
						var dDistanceToNearestPoint = nearestPoint ? nearestPoint[1] : Number.MAX_VALUE;
						if (nNearestPointIndex >= 0 && nNearestPointIndex < data.aPoints.length && dDistanceToNearestPoint < dThreshold)
						{
							nIndex = nNearestPointIndex;
							bMovePoint = true;
						}
						else if (!bDeletePoint)
						{					
							var nearestLine = SIX.Util.getNearestLine(map.dMouseWorldX, map.dMouseWorldY, data.aPoints);
							var nNearestLineIndex = nearestLine ? nearestLine[0] : -1;
							var dDistanceToNearestLine = nearestLine ? nearestLine[1] : Number.MAX_VALUE;
							if (nNearestLineIndex >= 0 && nNearestLineIndex < data.aPoints.length - 1 && dDistanceToNearestLine < dThreshold)
								nIndex = nNearestLineIndex + 1;
						}
					
						if (bDeletePoint)
						{
							if (data.aPoints.length && nIndex < data.aPoints.length)
							{
								data.aPoints.splice(nIndex, 1);
								data.aPixelsX.splice(nIndex, 1);
								data.aPixelsY.splice(nIndex, 1);
							}								
						}
						else if (nIndex == data.aPoints.length)
						{
							data.aPoints[nIndex] = new SIX.Point(map.dMouseWorldX, map.dMouseWorldY);
							data.aPixelsX[nIndex] = map.dMouseScreenX;
							data.aPixelsY[nIndex] = map.dMouseScreenY;						
						}
						else
						{
							data.aPoints.splice(nIndex, (bMovePoint ? 1 : 0), new SIX.Point(map.dMouseWorldX, map.dMouseWorldY));
							data.aPixelsX.splice(nIndex, (bMovePoint ? 1 : 0), map.dMouseScreenX);
							data.aPixelsY.splice(nIndex, (bMovePoint ? 1 : 0), map.dMouseScreenY);						
						}
						
						data.nSelectedIndex = bDeletePoint ? -1 : nIndex;	
						data.update(map);
					}		
				}, toolData);		

	this.addCallback(SIX.eToolCallbacks.ONMAPMOUSEMOVE, 
				function (map, data) {
					if (data.nSelectedIndex >= 0 && data.nSelectedIndex < data.aPoints.length)
					{					
						var nIndex = data.nSelectedIndex;
					
						if (nIndex == data.aPoints.length)
						{
							data.aPoints[nIndex] = new SIX.Point(map.dMouseWorldX, map.dMouseWorldY);
							data.aPixelsX[nIndex] = map.dMouseScreenX;
							data.aPixelsY[nIndex] = map.dMouseScreenY;						
						}
						else
						{
							data.aPoints.splice(nIndex, 1, new SIX.Point(map.dMouseWorldX, map.dMouseWorldY));
							data.aPixelsX.splice(nIndex, 1, map.dMouseScreenX);
							data.aPixelsY.splice(nIndex, 1, map.dMouseScreenY);						
						}
						
						data.update(map);
					}	
				}, toolData);	

	if (SIX.App.bDHTMLControl)
	{				
		this.addCallback(SIX.eToolCallbacks.ONMAPEXTENTCHANGE, 
					function (map, data) {			
						data.update(map, true);		
					}, toolData);
	}						
}
SIX.Util.extend(SIX.Tool.Measure, SIX.Tool);