
//constructor
var MapDrawingTool = function(){};

MapDrawingTool.points = [];
MapDrawingTool.currentSegmentPoints = [];
MapDrawingTool.shapes = {
	polygon: null, 
	polyline: null,
	line_segment: null
};
MapDrawingTool.enableMarginAutoPan = false;
MapDrawingTool.callback = null;
MapDrawingTool.prototype.setCallback = function(callback){
	//REQUIRED:  sets the function to return the drawing result object to
	MapDrawingTool.callback = callback;
};


MapDrawingTool.prototype.enableDrawing = function(){
	//initialize the point and distance variables
    MapDrawingTool.points = [];
    MapDrawingTool.currentSegmentPoints = [];
    
	MapDrawingTool.shapeLayer = getShapeLayerByTitle('drawingLayer',true);
	
    map.AttachEvent("onclick", MapDrawingTool.prototype.click);
    map.AttachEvent("ondoubleclick", MapDrawingTool.prototype.doubleClick);
    map.AttachEvent("onendpan", MapDrawingTool.prototype.renderShapes);
    map.AttachEvent("onendzoom", MapDrawingTool.prototype.renderShapes);

	if (MapDrawingTool.enableMarginAutoPan){
		//enable auto-panning when cursor enters margins
	    setPanBounds();
	    map.AttachEvent("onendpan", setPanBounds);
	    map.AttachEvent("onendzoom", setPanBounds);
	    map.AttachEvent("oninitmode", setPanBounds);
	}

    setMapCursor('crosshair');
    map.vemapcontrol.EnableGeoCommunity(true); //must be set to true for autopanning
}

MapDrawingTool.prototype.disableDrawing = function(){
	MapDrawingTool.currentSegmentPoints = [];
	
		try { MapDrawingTool.shapeLayer.DeleteAllShapes(); }
		catch (e){}
	    try { map.DetachEvent("onclick", MapDrawingTool.prototype.click);}
		catch (e){}
        try { map.DetachEvent("ondoubleclick", MapDrawingTool.prototype.doubleClick); }
		catch (e){}
        try { map.DetachEvent("onendpan", MapDrawingTool.prototype.renderShapes ); }
		catch (e){}
        try { map.DetachEvent("onendzoom", MapDrawingTool.prototype.renderShapes);} 
		catch (e) {}
		try {map.DetachEvent("onmousemove", MapDrawingTool.prototype.move);} 
		catch (e) {}
	
	setMapCursor('hand'); //reset map cursor to default
    map.vemapcontrol.EnableGeoCommunity(false); //must be false to reenable default mouse events
}

MapDrawingTool.prototype.reset = function(){
	//clear current drawing and detach mouse move event
	MapDrawingTool.points = [];
	MapDrawingTool.shapeLayer.DeleteAllShapes();
	try {map.DetachEvent("onmousemove", MapDrawingTool.prototype.move);} 
	catch (e) {}
}

MapDrawingTool.prototype.click = function(e){
	var LL = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
    MapDrawingTool.points.push(LL);  //add clicked point to array
    
	//reset if user clicked the right-mouse button
	if (e.rightMouseButton) {
		MapDrawingTool.prototype.reset();
		return;
	}
	
	 //if click is within close enough distance of first point close/draw the polygon
	if (MapDrawingTool.points.length >= 3 && MapDrawingTool.prototype.isPolygon() == true) {
    
        //complete the polygon shape
		MapDrawingTool.prototype.disableDrawing();
        MapDrawingTool.points.push(MapDrawingTool.points[0]);
        MapDrawingTool.prototype.renderShapes();
        MapDrawingTool.prototype.complete();
	 	}
	else {
		map.AttachEvent("onmousemove", MapDrawingTool.prototype.move);
	    MapDrawingTool.prototype.renderShapes();  
	}
}

MapDrawingTool.prototype.doubleClick = function(e){
	
	//complete the polygon if there are enough points.
	//we use >= 4 since the click event is also fired and adds a point
    if (MapDrawingTool.points.length >= 4) {
		MapDrawingTool.prototype.disableDrawing();
		MapDrawingTool.points.push(MapDrawingTool.points[0]);
		MapDrawingTool.prototype.renderShapes();
		MapDrawingTool.prototype.complete();
	}
	else {
		MapDrawingTool.prototype.reset();
		alert('You must draw more than 2 points.');
	}

    //Return true to override the Virtual Earth default double-click event
    return true;
}

MapDrawingTool.prototype.move = function(e) {
    setMapCursor('crosshair');
    
	//create an array with 2 points...  one with the last point clicked
	//by the user and one with a point for the current mouse location
    MapDrawingTool.currentSegmentPoints = [];
    MapDrawingTool.currentSegmentPoints[0] = MapDrawingTool.points[MapDrawingTool.points.length - 1]; //grab last point
	var LL = map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
	MapDrawingTool.currentSegmentPoints.push(LL);

    try {
        MapDrawingTool.shapeLayer.DeleteShape(MapDrawingTool.shapes.line_segment);
    }
    catch (err) { }

    //update line shape as user moves mouse
    if (MapDrawingTool.currentSegmentPoints.length > 1) {
        var s = new VEShape(VEShapeType.Polyline, MapDrawingTool.currentSegmentPoints);
        s.SetLineWidth(2);
        s.SetLineColor(new VEColor(000, 191, 255, 1.0));
        s.HideIcon();
		MapDrawingTool.shapes.line_segment = s;
        MapDrawingTool.shapeLayer.AddShape(MapDrawingTool.shapes.line_segment);
		
    }

	if (MapDrawingTool.enableMarginAutoPan) {
		//code for autopanning
		var panAmount = 10;
		
		//determine direction
		if (previousLL) {
			latVariance = LL.Latitude - previousLL.Latitude;
			longVariance = LL.Longitude - previousLL.Longitude;
			
			//pan map
			if ((LL.Latitude < southBound) && (latVariance < 0)) {
				map.Pan(0, panAmount);
			}
			if ((LL.Latitude > northBound) && (latVariance > 0)) {
				map.Pan(0, panAmount * -1);
			}
			if ((LL.Longitude < westBound) && (longVariance < 0)) {
				map.Pan(panAmount * -1, 0);
			}
			if ((LL.Longitude > eastBound) && (longVariance > 0)) {
				map.Pan(panAmount, 0);
			}
		}
		
		previousLL = LL;
	}
}

MapDrawingTool.prototype.restart = function(e) {
    MapDrawingTool.prototype.enableDrawing();
    MapDrawingTool.prototype.click(e);
}


//this code allows for automatic panning of map when cursor approaches the map border when using drawing tool.
//it was modified from code by Mike Garza at http://garzilla.net/vemaps/MovePushPin4.aspx
//It also requires additions to the drawingMouseMove  function (see comments), global variable declarations,
//and setting the map.vemapcontrol.EnableGeoCommunity property to true (which is done in startDrawingTool())

var previousLL;
var northBound;
var southBound;
var westBound;
var eastBound;

function setPanBounds() {
    
    view = map.GetMapView();
    topLeft = map.LatLongToPixel(view.TopLeftLatLong);
    bottomRight = map.LatLongToPixel(view.BottomRightLatLong);
    
    var panBuffer = 50; 
    var NBound = topLeft.x + panBuffer;
    var SBound = bottomRight.x - panBuffer;
    var EBound = bottomRight.y - panBuffer;
    var WBound = topLeft.y + panBuffer;

    var topLeftBound = map.PixelToLatLong(new VEPixel(NBound, WBound));
    var bottomRightBound = map.PixelToLatLong(new VEPixel(SBound, EBound));

    northBound = topLeftBound.Latitude;
    southBound = bottomRightBound.Latitude;
    westBound = topLeftBound.Longitude;
    eastBound = bottomRightBound.Longitude;

}

MapDrawingTool.prototype.renderShapes = function() {
    //due to a bug where shape stays in fixed position and scale regardless
    //of pans/zooms, shape drawing was moving to this function which is called
    //on mouse clicks, mouse moves, end zooms, and end pans.

    MapDrawingTool.shapeLayer.DeleteAllShapes();

	//draw polyline if more than one point
    if (MapDrawingTool.points.length > 1) {
        var l = new VEShape(VEShapeType.Polyline, MapDrawingTool.points);
        l.SetLineWidth(2);
        l.SetLineColor(new VEColor(070, 130, 180, 1.0));
        l.HideIcon();
		MapDrawingTool.shapes.polyline = l;
        MapDrawingTool.shapeLayer.AddShape(MapDrawingTool.shapes.polyline);
    }

    //redraw polygon if applicable
    if (MapDrawingTool.points.length > 2) {
	    //MapDrawingTool.shapeLayer.DeleteAllShapes();
	    
	    //create a polygon
	    var p = new VEShape(VEShapeType.Polygon, MapDrawingTool.points);
	    p.SetLineWidth(2);
	    p.SetLineColor(new VEColor(070, 130, 180, 0));
	    p.SetFillColor(new VEColor(255, 165, 79, .5));
	    p.HideIcon();
		MapDrawingTool.shapes.polygon = p;
	    MapDrawingTool.shapeLayer.AddShape(MapDrawingTool.shapes.polygon);
    }

}


MapDrawingTool.prototype.isPolygon = function() {
	//determines whether last point clicked is close enough to first point
	//to be considered an attempt at closing the polygon.
	
	var tolerance = 6;  //tolerance in pixel distance
	
	//only test if we have at least 3 points
    if (MapDrawingTool.points.length >= 3) {
        
        var pixels;
        map.LatLongToPixel(MapDrawingTool.points, map.GetZoomLevel(), function(results) {
            pixels = results;
        });

		//use pythagoras theorum to get distance between pixels
        var p1 = pixels[0]; p2 = pixels[pixels.length - 1];
        var a = p2.x - p1.x; //x diff
        var b = p2.y - p1.y; //y diff
		var distance = Math.sqrt((a*a) + (b*b));
		
        if (distance <= tolerance) return true;
		else return false;
    }
    else return false;

}

MapDrawingTool.prototype.complete = function(){
	//this function finishes the drawing process and calls the callback function
	
	//create a string containing all coordinates in polygon
	var points = MapDrawingTool.shapes.polygon.GetPoints();
	var coordinates = '';
	for (var j = 0; j < (points.length); j++) {
		coordinates = coordinates + points[j].Longitude.toFixed(6) + " " + points[j].Latitude.toFixed(6) + ", ";
	}
	coordinates = coordinates.substr(0, coordinates.length - 2); //remove trailing chars
	
	//build and return our results to the callback function
	var drawingResultObj = {
		polygonShape: MapDrawingTool.shapes.polygon,
		coordinateString: coordinates
	}
	
	MapDrawingTool.callback(drawingResultObj);
	//MapDrawingTool.prototype.reset();
}

