if(!Terrascape.DefaultMapper) {
	Terrascape.DefaultMapper = {};
}
Terrascape.DefaultMapper.DefaultHandler = Class.create();
Terrascape.DefaultMapper.DefaultHandler.prototype = {
	initialize: function(mapper) {
		this.type = "default";
		this.mapper = mapper;
		this.mapDisplay = mapper.mapDisplay;
	},
	mouseDown: function(e) {
	},
	mouseMove: function(e) {
		var p0 = this.mapDisplay.containerPointToWorld(e.point);
		window.status = p0.x.toFixed(3) + " : " + p0.y.toFixed(3);
	},
	mouseUp: function(e) {
	},
	destroy: function() {
	}
};

Terrascape.DefaultMapper.ZoomInHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "zoomIn";
	},
	mouseDown: function(e) {
		if(this.zoomRect) {
			this.mapDisplay.removeShape(this.zoomRect);
			this.zoomRect = null;
		}
		this.start = this.mapDisplay.containerPointToMap(e.point);
		this.zoomRect = new Terrascape.Rect({
			x: this.start.x,
			y: this.start.y,
			strokeColor: "blue",
			strokeOpacity: 0.6,
			strokeWidth: "0.05%",
			fillColor: "blue",
			fillOpacity: 0.2
		});
		this.mapDisplay.addShape(this.zoomRect);
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - zooming";
		if(this.start) {
			this.end = this.mapDisplay.containerPointToMap(e.point);
			Terrascape.DefaultMapper.moveRect(this.mapDisplay, this.zoomRect, this.start, this.end);
		}
	},
	mouseUp: function(e) {
		if (this.zoomRect.width < config.zoomBoxMinSize || this.zoomRect.height < config.zoomBoxMinSize) {
			this.mapDisplay.zoomToPoint(e.point);
		} else {
			this.mapDisplay.zoomToRect(this.zoomRect.toRect());
		}
		this.destroy();
	},
	destroy: function() {
		this.start = null;
		this.end = null;
		if(this.zoomRect) {
			this.mapDisplay.removeShape(this.zoomRect);
			this.zoomRect = null;
		}
	}
});

Terrascape.DefaultMapper.ZoomOutHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "zoomOut";
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - zooming out";
	},
	mouseUp: function(e) {
		this.mapDisplay.zoomFromPoint(e.point);
	}
});

Terrascape.DefaultMapper.CenterHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "center";
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - centering";
	},
	mouseUp: function(e) {
		this.mapDisplay.centerOnPoint(e.point);
	}
});

Terrascape.DefaultMapper.PanHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "pan";
	},
	mouseDown: function(e) {
		this.start = e.point;
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - panning";
		if(this.start) {
			var pt = new Point(this.start.x - e.point.x, this.start.y - e.point.y);
			this.mapDisplay.panByPixels(-pt.x, -pt.y);
			this.start = e.point;
		window.status += " - panning";
		}
	},
	mouseUp: function(e) {
		this.destroy();
	},
	destroy: function() {
		this.start = null;
		this.end = null;
	}
});

Terrascape.DefaultMapper.MeasureHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "measure";
	},
	mouseDown: function(e) {
		this.start = this.mapDisplay.containerPointToMap(e.point);
		this.measureLine = new Terrascape.Line({
			x: this.start.x,
			y: this.start.y,
			x1: this.start.x,
			y1: this.start.y,
			strokeColor: "blue",
			strokeOpacity: 0.6,
			strokeWidth: "0.2%"
		});
		this.mapDisplay.addShape(this.measureLine);
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - measuring";
		if(this.start) {
			this.end = this.mapDisplay.containerPointToMap(e.point);
			this.measureLine.x1 = this.end.x;
			this.measureLine.y1 = this.end.y;
			this.mapDisplay.applyShape(this.measureLine);
		}
	},
	mouseUp: function(e) {
		var x = Math.abs(this.start.x - this.end.x);
		var y = Math.abs(this.start.y - this.end.y);
		config.displayResultMessage("<div class='measureresult'>Distance</div><div class='measureresult'>" + Math.sqrt(x * x + y * y).toFixed(1) + " m</div>");
		this.destroy();
	},
	destroy: function() {
		this.start = null;
		this.end = null;
		if(this.measureLine) {
			this.mapDisplay.removeShape(this.measureLine);
			this.measureLine = null;
		}
	}
});

Terrascape.DefaultMapper.SelectHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "select";
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - selecting";
	},
	mouseUp: function(e) {
		var layer = this.mapDisplay.getLayer(this.mapper.getSelectedLayer().id);
		var selectionLayer = this.mapDisplay.getLayer("__selectionLayer");
		if(!e.shift) {
			selectionLayer.clear();
		}
		var shape = this.mapDisplay.getShapeFromPoint(layer, this.mapDisplay.containerPointToMap(e.point));
		this.mapper.showSelection(shape, selectionLayer);
		config.displayHelpMessage(selectionLayer.getShapeCount() + " feature(s) selected.");
	}
});

Terrascape.DefaultMapper.AreaHandler = Class.extend(Terrascape.DefaultMapper.SelectHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "area";
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - calculating area";
	},
	mouseUp: function(e) {
		this.parent(e);
		var selectionLayer = this.mapDisplay.getLayer("__selectionLayer");
		if(selectionLayer.getShapeCount() == 0) {
			config.displayHelpMessage("Feature not on active layer");
			return;
		}
		var layer = this.mapDisplay.getLayer(this.mapper.getSelectedLayer().id);
		var layerData = Terrascape.MapData.getLayer(layer.id);
		var answer = 0;
		var shapes = selectionLayer.getShapes();
		shapes.each(function(shape) {
			var V = layerData.points[shape.id.substr(1)];
			if(V) {
				if(V[0] == V[V.length - 1]) {
					var V2 = new Array();
					for(var ii = 0; ii < V.length; ++ii) {
						V2[ii] = V[ii];
					}
					V2[V2.length] = V[1];
					answer += Math.abs(area2D_Polygon(V2.length - 2, V2));
				}
			}
		}.bind(this));
		if(answer == 0) {
			config.displayResultMessage("All selected features are line features.");
		} else {
			config.displayResultMessage("<div class='measureresult'>Area</div><div class='measureresult'>" + formatNumber(answer, 0) + " m<span class='measureresultsuper'>2</span></div>");
		}
	}
});

Terrascape.DefaultMapper.SelectQueryHandler = Class.extend(Terrascape.DefaultMapper.SelectHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "selectQuery";
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " and querying";
	},
	mouseUp: function(e) {
		this.parent(e);
		this.mapper.query();
	}
});

Terrascape.DefaultMapper.SelectFullHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "selectFull";
	},
	mouseDown: function(e) {
		this.start = this.mapDisplay.containerPointToMap(e.point);
		this.selectRect = new Terrascape.Rect({
			x: this.start.x,
			y: this.start.y,
			strokeColor: "yellow",
			strokeOpacity: 0.6,
			strokeWidth: "0.05%",
			fillColor: "yellow",
			fillOpacity: 0.2
		});
		this.mapDisplay.addShape(this.selectRect);
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - selecting";
		if(this.start) {
			this.end = this.mapDisplay.containerPointToMap(e.point);
			Terrascape.DefaultMapper.moveRect(this.mapDisplay, this.selectRect, this.start, this.end);
		}
	},
	mouseUp: function(e) {
		var layer = this.mapDisplay.getLayer(this.mapper.getSelectedLayer().id);
		var selectionLayer = this.mapDisplay.getLayer("__selectionLayer");
		if(!e.shift) {
			selectionLayer.clear();
		}
		var shapes = this.mapDisplay.getShapesInRect(layer, this.selectRect.toRect());
		shapes.each(function(shape) {
			this.mapper.showSelection(shape, selectionLayer);
		}.bind(this));
		config.displayHelpMessage(selectionLayer.getShapeCount() + " feature(s) selected.");
		this.destroy();
	},
	destroy: function() {
		this.start = null;
		this.end = null;
		if(this.selectRect) {
			this.mapDisplay.removeShape(this.selectRect);
			this.selectRect = null;
		}
	}
});

Terrascape.DefaultMapper.SelectPartialHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "selectPartial";
	},
	mouseDown: function(e) {
		this.start = this.mapDisplay.containerPointToMap(e.point);
		this.selectRect = new Terrascape.Rect({
			x: this.start.x,
			y: this.start.y,
			strokeColor: "yellow",
			strokeOpacity: 0.6,
			strokeWidth: "0.05%",
			fillColor: "yellow",
			fillOpacity: 0.2
		});
		this.mapDisplay.addShape(this.selectRect);
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - selecting " + (this.selectRect ? this.selectRect.toRect().toString() : "");
		if(this.start) {
			this.end = this.mapDisplay.containerPointToMap(e.point);
			Terrascape.DefaultMapper.moveRect(this.mapDisplay, this.selectRect, this.start, this.end);
		}
	},
	mouseUp: function(e) {
		var layer = this.mapDisplay.getLayer(this.mapper.getSelectedLayer().id);
		var selectionLayer = this.mapDisplay.getLayer("__selectionLayer");
		if(!e.shift) {
			selectionLayer.clear();
		}
		var shapes = this.mapDisplay.getShapesIntersectRect(layer, this.selectRect.toRect());
		shapes.each(function(shape) {
			this.mapper.showSelection(shape, selectionLayer);
		}.bind(this));
		config.displayHelpMessage(selectionLayer.getShapeCount() + " feature(s) selected.");
		this.destroy();
	},
	destroy: function() {
		this.start = null;
		this.end = null;
		if(this.selectRect) {
			this.mapDisplay.removeShape(this.selectRect);
			this.selectRect = null;
		}
	}
});

Terrascape.DefaultMapper.moveRect = function(mapDisplay, shape, start, end) {
	var s = start.clone();
	var e = end.clone();
	if(s.x > e.x) {
		var t = e.x;
		e.x = s.x;
		s.x = t;
	}
	if(s.y > e.y) {
		var t = e.y;
		e.y = s.y;
		s.y = t;
	}
	shape.x = s.x;
	shape.y = s.y;
	shape.width = e.x - s.x;
	shape.height = e.y - s.y;
	window.status = shape.width + ":" + shape.height;
	mapDisplay.applyShape(shape);
};

Terrascape.DefaultMapper.PolyAreaHandler = Class.extend(Terrascape.DefaultMapper.DefaultHandler, {
	initialize: function(mapper) {
		this.parent(mapper);
		this.type = "polyArea";
	},
	mouseDown: function(e) {
	},
	mouseMove: function(e) {
		this.parent(e);
		window.status += " - measuring polygon area";
	},
	mouseUp: function(e) {
		if(this.start) {
			var p = this.mapDisplay.containerPointToMap(e.point);
			this.polyArea.points.add(p);
			this.mapDisplay.applyShape(this.polyArea);
			if((this.start.x - p.x)*(this.start.x - p.x) + (this.start.y - p.y)*(this.start.y - p.y) < this.min) {
				this.start = null;
			}
		} else {
			if(this.polyArea) {
				this.destroy();
			}
			var rect = this.mapDisplay.getViewBox();
			this.min = Math.min(rect.w / 10, rect.h / 10);
			this.start = this.mapDisplay.containerPointToMap(e.point);
			this.polyArea = new Terrascape.Polygon({
				x: this.start.x,
				y: this.start.y,
				strokeColor: "blue",
				strokeOpacity: 0.6,
				strokeWidth: "0.05%",
				fillColor: "blue",
				fillOpacity: 0.2,
				points: [ this.start ]
			});
			this.mapDisplay.addShape(this.polyArea);
		}

		var V2 = [];
		for(var ii = 0; ii < this.polyArea.points.length; ++ii) {
			V2[ii] = this.polyArea.points[ii];
		}
		if(V2[V2.length - 1] != V2[0]) {
			V2.add(this.polyArea.points[0]);
		}
		V2.add(this.polyArea.points[1]);
		var A = Math.abs(area2D_Polygon(V2.length - 2, V2));
		config.displayResultMessage("<div class='measureresult'>Area</div><div class='measureresult'>" + A.toFixed(0) + " m<span class='measureresultsuper'>2</span></div>");

	},
	destroy: function() {
		this.start = null;
		if(this.polyArea) {
			this.mapDisplay.removeShape(this.polyArea);
			this.polyArea = null;
		}
	}
});

Terrascape.DefaultMapper.GridHandler = Class.create();
Terrascape.DefaultMapper.GridHandler.prototype = {
	initialize: function(type, button, mapDisplay) {
		this.gridLoaded = false;
		this.gridVisible = false;
		this.gridLayers = [];
		this.gridType = type;
		this.button = button;
		this.mapDisplay = mapDisplay;
	},
	execute: function() {
		if(!this.gridLoaded) {
			getServerData("data.aspx?object=mapper&action=getgridlist&grid=" + this.gridType + "&managementsystemid=" + Terrascape.MapView.managementSystemId, this.dataLoaded.bind(this));
			config.displayHelpMessage("Loading " + this.gridType + "grid...");
			this.button.Select(true);
			this.gridLoaded = true;
			return;
		}
		this.gridVisible = !this.gridVisible;
		for(var i = 0; i < this.gridLayers.length; ++i) {
			this.mapDisplay.setLayerVisibility(this.gridLayers[i], this.gridVisible);
			this.mapDisplay.setLayerVisibility("l" + this.gridLayers[i], this.gridVisible);
		}
		this.button.Select(this.gridVisible);
	},
	dataLoaded: function(xml) {
		if(checkServerDataStatus(xml)) {
			for(var i = 0; i < xml.firstChild.childNodes.length; ++i) {
				var data = xml.firstChild.childNodes[i];
				this.gridLayers.add(data.attributes.getNamedItem("id").value);
				loadSvgLayer("data.aspx?object=mapper&action=loadlayer&managementsystemid=" + Terrascape.MapView.managementSystemId + "&categoryid=" + data.attributes.getNamedItem("categoryid").value + "&layerid=" + data.attributes.getNamedItem("id").value + "&boundsx=" + this.mapDisplay.bounds.x + "&boundsy=" + this.mapDisplay.bounds.y + "&boundsw=" + this.mapDisplay.bounds.w + "&boundsh=" + this.mapDisplay.bounds.h);
				loadSvgLayer("data.aspx?object=mapper&action=loadlabels&managementsystemid=" + Terrascape.MapView.managementSystemId + "&categoryid=" + data.attributes.getNamedItem("categoryid").value + "&layerid=" + data.attributes.getNamedItem("id").value + "&boundsx=" + this.mapDisplay.bounds.x + "&boundsy=" + this.mapDisplay.bounds.y + "&boundsw=" + this.mapDisplay.bounds.w + "&boundsh=" + this.mapDisplay.bounds.h);
			}
		}
		config.displayDefaultHelpMessage();
	}
};

