// Fred 2014 (adapted from https://github.com/jtreml/leaflet.measure)

L.Control.MeasureArea = L.Control.extend({
	options: {
		position: 'topleft'
	},

	onAdd: function (map) {
            
		var className = 'leaflet-control-zoom leaflet-bar leaflet-control leaflet-control-area',
		    container = L.DomUtil.create('div', className);

		this._createButton('&#8718;', 'Measure Area', 'leaflet-control-measure leaflet-bar-part leaflet-bar-part-top-and-bottom', container, this._toggleMeasureArea, this);

		return container;
	},

	_createButton: function (html, title, className, container, fn, context) {
		var link = L.DomUtil.create('a', className, container);
		link.innerHTML = html;
		link.href = '#';
		link.title = title;

		L.DomEvent
			.on(link, 'click', L.DomEvent.stopPropagation)
			.on(link, 'click', L.DomEvent.preventDefault)
			.on(link, 'click', fn, context)
			.on(link, 'dblclick', L.DomEvent.stopPropagation);

		return link;
	},

	_toggleMeasureArea: function () {
            
                if (controlMeasure && controlMeasure._measuring) {
                    controlMeasure._measuring = false;
                    L.DomUtil.removeClass(controlMeasure._container, 'leaflet-control-measure-on');
                    controlMeasure._stopMeasuring();
                }
            
		this._measuring = !this._measuring;

		if(this._measuring) {
                        layerControl.resetIdentify();
			L.DomUtil.addClass(this._container, 'leaflet-control-measure-on');
			this._startMeasuring();
		} else {
			L.DomUtil.removeClass(this._container, 'leaflet-control-measure-on');
			this._stopMeasuring();
		}
	},

	_startMeasuring: function() {
		this._oldCursor = this._map._container.style.cursor;
		this._map._container.style.cursor = 'crosshair';

		this._doubleClickZoom = this._map.doubleClickZoom.enabled();
		this._map.doubleClickZoom.disable();

		L.DomEvent
			.on(this._map, 'mousemove', this._mouseMove, this)
			.on(this._map, 'click', this._mouseClick, this)
			.on(this._map, 'dblclick', this._finishPath, this)
			.on(document, 'keydown', this._onKeyDown, this);

		if(!this._layerPaint) {
			this._layerPaint = L.layerGroup().addTo(this._map);	
		}

		if(!this._points) {
			this._points = [];
		}
	},

	_stopMeasuring: function() {
		this._map._container.style.cursor = this._oldCursor;

		L.DomEvent
			.off(document, 'keydown', this._onKeyDown, this)
			.off(this._map, 'mousemove', this._mouseMove, this)
			.off(this._map, 'click', this._mouseClick, this)
			.off(this._map, 'dblclick', this._mouseClick, this);

		if(this._doubleClickZoom) {
			this._map.doubleClickZoom.enable();
		}

		if(this._layerPaint) {
			this._layerPaint.clearLayers();
		}
		
		this._restartPath();
	},

	_mouseMove: function(e) {
		if(!e.latlng || !this._lastPoint) {
			return;
		}
		
		if(!this._layerPaintPathTemp) {
			this._layerPaintPathTemp = L.polyline([this._lastPoint, e.latlng, this._firstPoint], { 
				color: 'black',
				weight: 1.5,
				clickable: false,
				dashArray: '6,3'
			}).addTo(this._layerPaint);
		} else {
			this._layerPaintPathTemp.spliceLatLngs(0, 2, this._lastPoint, e.latlng);
		}

                //console.log("Path bounds = " + this._layerPaintPathTemp.getBounds().getCenter());

		if(this._points.length > 2) {
                        var area = this._calcArea(this._points);
		} else {
                    return;
                }

                if (!this._tooltip) {
                    this._createTooltip(this._layerPaintPathTemp.getBounds().getCenter());
                } else {
			this._updateTooltipPosition(this._layerPaintPathTemp.getBounds().getCenter());

			//var distance = e.latlng.distanceTo(this._lastPoint);
                        var myPts = this._points.slice();
                        myPts.push(e.latlng);
                        var area = this._calcArea(myPts);
			this._updateTooltipArea(area); 
                }
	},


	_mouseClick: function(e) {
		// Skip if no coordinates
		if(!e.latlng) {
			return;
		}
            
               if (!this._firstPoint) {
                   this._firstPoint = e.latlng;
               }
               
               this._points.push(e.latlng);
  


                if (this._points.length == 3) {
                    var area = this._calcArea(this._points);
                    if (!this._tooltip) {
                        this._createTooltip(this._layerPaintPathTemp.getBounds().getCenter());
                    }
                }
	
		if(this._lastPoint && !this._layerPaintPath) {
			this._layerPaintPath = L.polyline([this._lastPoint], { 
				color: 'black',
				weight: 2,
				clickable: false
			}).addTo(this._layerPaint);
		}



		if(this._layerPaintPath) {
			this._layerPaintPath.addLatLng(e.latlng);
		}

		// Upate the end marker to the current location
		if(this._lastCircle) {
			this._layerPaint.removeLayer(this._lastCircle);
		}

		this._lastCircle = new L.CircleMarker(e.latlng, { 
			color: 'black', 
			opacity: 1, 
			weight: 1, 
			fill: true, 
			fillOpacity: 1,
			radius:2,
			clickable: this._lastCircle ? true : false
		}).addTo(this._layerPaint);
		
		this._lastCircle.on('click', function() { this._finishPath(); }, this);

		// Save current location as last location
		this._lastPoint = e.latlng;
	},

	_finishPath: function() {
		// Remove the last end marker as well as the last (moving tooltip)

		if(this._layerPaintPath) {
			this._layerPaint.removeLayer(this._layerPaintPath);
		}

                this._layerPolyArea = L.polygon([this._points], { 
                        color: 'black',
                        weight: 2,
                        clickable: false
                }).addTo(this._layerPaint);
                
                this._updateTooltipPosition(this._layerPolyArea.getBounds().getCenter());
                
     
		if(this._lastCircle) {
			this._layerPaint.removeLayer(this._lastCircle);
		}
		if(this._layerPaint && this._layerPaintPathTemp) {
			this._layerPaint.removeLayer(this._layerPaintPathTemp);
		}

		// Reset everything
		this._restartPath();
	},

	_restartPath: function() {
		this._distance = 0;
		this._tooltip = undefined;
		this._lastCircle = undefined;
                this._firstPoint = undefined;
		this._lastPoint = undefined; // + fred
                this._points = []; // +fred
		this._layerPaintPath = undefined;
		this._layerPaintPathTemp = undefined;
	},
	
	_createTooltip: function(position) {
		var icon = L.divIcon({
			className: 'leaflet-measure-tooltip',
			iconAnchor: [-5, -5]
		});
		this._tooltip = L.marker(position, { 
			icon: icon,
			clickable: false
		}).addTo(this._layerPaint);
	},

	_updateTooltipPosition: function(position) {
		this._tooltip.setLatLng(position);
	},

	_updateTooltipArea: function(total) {
                if (total > 100000) {
                    var text = '<div class="leaflet-measure-tooltip-total">' + Math.round((total / 1000000) * 10) / 10 + ' km2</div>';
                } else {
                    var text = '<div class="leaflet-measure-tooltip-total">' + Math.round((total) * 10) / 10 + ' m2</div>';
                }

		this._tooltip._icon.innerHTML = text;
	},

	_onKeyDown: function (e) {
		if(e.keyCode == 27) {
			// If not in path exit measuring mode, else just finish path
			if(!this._lastPoint) {
				this._toggleMeasureArea();
			} else {
				this._finishPath();
			}
		}
	},

        _calcArea: function(latLngs) {
            var pointsCount = latLngs.length,
                    area = 0.0,
                    d2r = L.LatLng.DEG_TO_RAD,
                    p1, p2;

            if (pointsCount > 2) {
                for (var i = 0; i < pointsCount; i++) {
                    p1 = latLngs[i];
                    p2 = latLngs[(i + 1) % pointsCount];
                    area += ((p2.lng - p1.lng) * d2r) *
                            (2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r));
                }
                area = area * 6378137.0 * 6378137.0 / 2.0;
            }

            return Math.abs(area);
        },
        

});

L.Map.mergeOptions({
	measureControl: false
});

L.Map.addInitHook(function () {
	if (this.options.measureAreaControl) {
		this.measureAreaControl = new L.Control.MeasureArea();
		this.addControl(this.measureAreaControl);
	}
});

L.control.measureArea = function (options) {
	return new L.Control.MeasureArea(options);
};


