L.Control.Measure = L.Control.extend({

    //是否初始化
    _initialized: false,

    //统计
    _lC: 0,
    //测量对象集合
    _measureObjs: {},
    //是否完成当前测绘
    _finished: true,

    //新测量
    isNewElevation: true,

    moveMarker: false,

    //测量参数
    options: {
        position: 'topright',
        autoZIndex: true,
        offset: [10, 10],
        background: "#000",
        color: "#fff",
        size: 14,
        closeButton: true
    },

    initialize: function(options) {
        L.setOptions(this, options);
        return this;
    },

    onAdd: function(map) {
        this._map = map;
        this._createControl();
        switch (this.options.position) {
            case 'topleft':
                this._container.style.marginLeft = this.options.offset[0] + 'px';
                this._container.style.marginTop = this.options.offset[1] + 'px';
                break;
            case 'topright':
                this._container.style.marginRight = this.options.offset[0] + 'px';
                this._container.style.marginTop = this.options.offset[1] + 'px';
                break;
            case 'bottomleft':
                this._container.style.marginLeft = this.options.offset[0] + 'px';
                this._container.style.marginBottom = this.options.offset[1] + 'px';
                break;
            case 'bottomright':
                this._container.style.marginRight = this.options.offset[0] + 'px';
                this._container.style.marginBottom = this.options.offset[1] + 'px';
                break;
        }
        return this._container;
    },

    _createControl: function() {
        var _this = this;
        this._container = L.DomUtil.create('div', 'leaflet-bar leaflet-control-measure');

        var link = L.DomUtil.create('a', 'leaflet-control-measure-link', this._container);
        link.title = '测量';
        L.DomUtil.create('span', '', link);

        L.DomEvent
            .on(this._container, 'contextmenu', L.DomEvent.stopPropagation)
            .on(link, 'click', L.DomEvent.stopPropagation)
            .on(link, 'click', function() {
                if (_this._finished) { //开启新的测量
                    _this.start();
                } else {
                    _this._finished = true;
                }
            })
        _this.start();
    },

    start: function() {
        var _this = this;
        _this._finished = false;
        L.DomUtil.addClass(_this._container, 'active');
        _this._addMeasureGroup();
    },

    _addMeasureGroup: function() {
        var _this = this;
        if (!_this._initialized) {
            _this._measureGroup = new L.featureGroup();
            _this._measureGroup.addTo(this._map);
            _this._initialized = true;
        }
        if (_this.isNewElevation) {
            _this._lC++;
            _this._measureObjs[_this._lC] = new L.FeatureGroup();
            _this._measureObjs[_this._lC].addTo(_this._measureGroup);
            _this.isNewElevation = false;
            _this._measureObjs[_this._lC].measurePoints = [];
        }
        _this.tmpMarkers = [];
        //关闭地图双击事件
        this._map.doubleClickZoom.disable();
        //监听地图单击事件
        this._map.on('click', _this._onClickPoint, this);
        //监听鼠标移动事件
        this._map.on('mousemove', _this._mousemove, this);
    },

    _mousemove: function(e) {
        var _this = this;
        e.latlng = _this.latlngRectifying(e);
        if (_this.moveMarker) {
            _this.moveMarker.setLatLng(e.latlng);
            if (_this._measureObjs[_this._lC].polyline) {
                _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
                var points = _this._measureObjs[_this._lC].measurePoints;
                if (_this._measureObjs[_this._lC].measurePoints.length == 2) {
                    var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
                    _this._measureObjs[_this._lC].circle.setRadius(radius);
                } else if (_this._measureObjs[_this._lC].measurePoints.length == 3 && e.latlng.indexMarker == 1) {
                    _this._measureObjs[_this._lC].circle.setStyle({
                        opacity: 1
                    })
                } else {
                    _this._measureObjs[_this._lC].circle.setStyle({
                        opacity: 0
                    })
                }
                if (_this._measureObjs[_this._lC].measurePoints.length > 2) {
                    var coors = _this._clone(_this._measureObjs[_this._lC].measurePoints);
                    coors.push(_this._measureObjs[_this._lC].measurePoints[_this._measureObjs[_this._lC].measurePoints.length - 1]);
                    if (_this._measureObjs[_this._lC].polygon) {
                        _this._measureObjs[_this._lC].polygon.setLatLngs([coors]);
                    } else {
                        _this._measureObjs[_this._lC].polygon = L.polygon([coors], {
                            color: "#fff",
                            weight: 0,
                            fillColor: "#fff",
                            fillOpacity: 0.3
                        }).addTo(_this._measureObjs[_this._lC]);
                    }
                }
                _this._measureObjs[_this._lC].polyline.setLatLngs(points);
                //实时计算测量数据
                var moveData = _this._clone(points);
                _this._moveInfo(moveData);
                _this._measureObjs[_this._lC].measurePoints.pop();
            }
        } else {
            _this.moveMarker = L.circleMarker(e.latlng, {
                radius: 10,
                color: "#f00"
            }).addTo(_this._map)
        }
    },
    _clone:function(data){
        data = JSON.parse(JSON.stringify(data));
        return data;
    },
    //测量时，根据鼠标移动点位信息
    _moveInfo:function(data){
        var _this = this;
        var lineDistance = 0;
        for (var i = 1; i < data.length; i++) {
            var curcoor = data[i];
            var prePoint = data[i - 1];
            lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
            var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
            if(i == data.length-1){
                var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
            }
        }
        //添加分段信息
        var oLabelObj = L.DomUtil.create('div', 'measure-content');
        var pointText = L.DomUtil.create('span', 'measure-result-text');
        pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
        oLabelObj.appendChild(pointText);
        if(data.length > 1){
            if(_this.tmpMarkers[data.length - 2]){//如果最后一个点存在，更新最后一个点信息
                _this.tmpMarkers[data.length - 2].setLatLng(data[data.length - 1]);
                _this.tmpMarkers[data.length - 2].label.setContent(oLabelObj);
            }else{//如果最后一个点不存在，创建点信息
                var marker = L.marker(data[data.length - 1], {icon: L.divIcon({ className: 'measuremarker', iconSize: [4, 4] }) });
                marker.bindLabel(oLabelObj,{ noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] });
                marker.addTo(_this._measureObjs[_this._lC]);
                _this.tmpMarkers.push(marker);
            }
        }
    },

    /**
     * 通过坐标点计算面积
     * @type {Function}
     * @returns {Number} 面积
     * @private
     */
    _getArea: function(_lc) {
        var _this = this;
        var latLngs = _this._measureObjs[_lc].measurePoints;
        var pointsCount = latLngs.length,
            area = 0.0,
            d2r = Math.PI / 180,
            p1, p2;
        if (pointsCount > 2) {
            for (var i = 0; i < pointsCount; i++) {
                p1 = latLngs[i];
                p2 = latLngs[(i + 1) % pointsCount];
                area += ((p2[1] - p1[1]) * d2r) *
                    (2 + Math.sin(p1[0] * d2r) + Math.sin(p2[0] * d2r));
            }
            area = area * 6378137.0 * 6378137.0 / 2.0;
        }

        area = Math.abs(area);

        if (area > 1000000) {
            area = (area * 0.000001).toFixed(2) + ' 平方公里';
        } else {
            area = area.toFixed(2) + ' 米&sup2;';
        }

        return area;
    },

    latlngRectifying: function(e) {
        var _this = this;
        var curLatlngs = [];
        var curpx = e.layerPoint;
        var length = _this._measureObjs[_this._lC] ? _this._measureObjs[_this._lC].measurePoints.length : 0;
        var latlng = e.latlng;
        if (length > 1) {
            curLatlngs.push({
                latlng: _this._measureObjs[_this._lC].measurePoints[0],
                px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[0])
            })
            curLatlngs.push({
                latlng: _this._measureObjs[_this._lC].measurePoints[length - 1],
                px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[length - 1])
            })
        }
        for (var i = 0; i < curLatlngs.length; i++) {
            var dispx = Math.sqrt((curpx.x - curLatlngs[i].px.x) * (curpx.x - curLatlngs[i].px.x) + (curpx.y - curLatlngs[i].px.y) * (curpx.y - curLatlngs[i].px.y));
            if (dispx < 10) {
                latlng = L.latLng(curLatlngs[i].latlng);
                latlng.reset = true;
                latlng.indexMarker = i;
                break;
            }
        }
        return latlng;
    },

    _onClickPoint: function(e) {
        var _this = this;
        e.latlng = _this.latlngRectifying(e);
        if (!e.latlng.reset) {
            _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
        } else {
            if (e.latlng.indexMarker == 0) {
                _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
                _this._measureObjs[_this._lC].polygon.setLatLngs(_this._measureObjs[_this._lC].measurePoints);
                _this._measureObjs[_this._lC].polygon.setStyle({
                    fillColor: "#f00",
                    color: "#f00",
                    weight: 0,
                    fillOpacity: 0.3
                });
            } else {
                _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].polygon);
                _this._measureObjs[_this._lC].polygon = null;
            }
            _this._onFinishClick();

        }

        if (_this._measureObjs[_this._lC].measurePoints.length == 1) {
            var latlngs = [
                [e.latlng.lat, e.latlng.lng],
                [e.latlng.lat, e.latlng.lng]
            ];

            _this._measureObjs[_this._lC].polyline = L.polyline(latlngs, { color: 'red', dashArray: 10 }).addTo(_this._measureObjs[_this._lC]);
            _this._measureObjs[_this._lC].circle = L.circle([e.latlng.lat, e.latlng.lng], { radius: 0, color: 'red', fillOpacity: 0 }).addTo(_this._measureObjs[_this._lC]);
        } else {
            // _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].circle);
        }
    },
    _onFinishClick: function() {
        _this = this;
        //关闭地图双击事件
        this._map.doubleClickZoom.enable();
        //监听地图单击事件
        this._map.off('click', _this._onClickPoint, this);
        //监听鼠标移动事件
        this._map.off('mousemove', _this._mousemove, this);
        _this.isNewElevation = true;
        _this._finished = true;
        _this._map.removeLayer(_this.moveMarker);
        _this.moveMarker = null;

        for(var i=0;i<_this.tmpMarkers.length;i++){
            _this._measureObjs[_this._lC].removeLayer(_this.tmpMarkers[i]);
        }
        _this.tmpMarkers = [];

        //根据点集合渲染marker点
        var coorslength = _this._measureObjs[_this._lC].measurePoints.length;
        _this._measureObjs[_this._lC].markerObjs = [];
        var lineDistance = 0;
        for (var i = 0; i < coorslength; i++) {
            var curcoor = _this._measureObjs[_this._lC].measurePoints[i];

            var marker = L.marker(curcoor, { draggable: true, icon: L.divIcon({ className: 'measuremarker', iconSize: [10, 10] }) });

            if (i > 0) {
                var prePoint = _this._measureObjs[_this._lC].measurePoints[i - 1];
                lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
                var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
                var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
                //添加分段信息
                var oLabelObj = L.DomUtil.create('div', 'measure-content');
                var delLabel = L.DomUtil.create('div', 'measure-ico-del');
                var pointText = L.DomUtil.create('span', 'measure-result-text');
                pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
                delLabel.lC = _this._lC;
                L.DomEvent.on(delLabel, 'click', function(e) {
                    L.DomEvent.stopPropagation(e);
                    _this.del(delLabel.lC)
                });
                if (i == coorslength - 1) {
                    //测量面积
                    if(_this._measureObjs[_this._lC].polygon){
                        var area = _this._getArea(_this._lC);
                        _this._measureObjs[_this._lC].area = area;
                        pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度'+'<br/>'+area;
                    }
                    oLabelObj.appendChild(delLabel);
                }
                oLabelObj.appendChild(pointText);
                marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] })
            }
            marker.LC = _this._lC;
            marker.LIndex = i;
            marker.addTo(_this._measureObjs[_this._lC]);
            _this._measureObjs[_this._lC].markerObjs.push(marker);
            if (!(i == 0 && _this._measureObjs[_this._lC].polygon)) {
                marker.on("move", function(e) {
                    _this._renderMeasure({
                        LC: e.target.LC,
                        LIndex: e.target.LIndex,
                        latlng: e.latlng
                    });
                })
            }
            marker.on("dragend", function(e) {
                this._map.fire('measure-result',{
                    distance:_this._measureObjs[e.target.LC].distance,
                    points:_this._measureObjs[e.target.LC].measurePoints,
                    area:_this._measureObjs[e.target.LC].area || 0,
                    LC:e.target.LC
                });
            })
        }
        _this._measureObjs[_this._lC].distance = lineDistance;
        
        this._map.fire('measure-result',{
            distance:_this._measureObjs[_this._lC].distance,
            points:_this._measureObjs[_this._lC].measurePoints,
            area:_this._measureObjs[_this._lC].area || 0,
            LC:_this._lC
        });
    },
    _renderMeasure: function(data) {
        var _this = this;
        var latlng = [data.latlng.lat, data.latlng.lng];
        _this._measureObjs[data.LC].measurePoints[data.LIndex] = latlng;
        var curlength = _this._measureObjs[data.LC].measurePoints.length;
        //如果是面，第一个点和最后一个点位置同时改变
        if (_this._measureObjs[data.LC].polygon) {
            if (data.LIndex == 0) {
                _this._measureObjs[data.LC].measurePoints[curlength - 1] = latlng;
                _this._measureObjs[_this._lC].markerObjs[curlength - 1].setLatLng(latlng);
            }
            if (data.LIndex == curlength - 1) {
                _this._measureObjs[data.LC].measurePoints[0] = latlng;
                _this._measureObjs[_this._lC].markerObjs[0].setLatLng(latlng);
            }
        }
        var points = _this._measureObjs[data.LC].measurePoints;
        //更新circle
        var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
        _this._measureObjs[data.LC].circle.setRadius(radius);
        _this._measureObjs[data.LC].circle.setLatLng(points[0]);
        if (points.length == 2) {
            _this._measureObjs[data.LC].circle.setStyle({
                opacity: 1
            })
        }

        //更新线
        _this._measureObjs[data.LC].polyline.setLatLngs(points);
        //更新面
        if (_this._measureObjs[data.LC].polygon) {
            _this._measureObjs[data.LC].polygon.setLatLngs([points]);
        }
        var lineDistance = 0;
        var coorslength = _this._measureObjs[data.LC].measurePoints.length;
        for (var i = 1; i < coorslength; i++) {
            var curcoor = _this._measureObjs[data.LC].measurePoints[i];
            var prePoint = _this._measureObjs[data.LC].measurePoints[i - 1];
            lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
            var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
            var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
            //添加分段信息
            var oLabelObj = L.DomUtil.create('div', 'measure-content');
            var delLabel = L.DomUtil.create('div', 'measure-ico-del');
            var pointText = L.DomUtil.create('span', 'measure-result-text');
            pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
            delLabel.lC = _this._lC;
            L.DomEvent.on(delLabel, 'click', function(e) {
                L.DomEvent.stopPropagation(e);
                _this.del(delLabel.lC)
            });
            if (i == coorslength - 1) {
                oLabelObj.appendChild(delLabel);
                //测量面积
                if(_this._measureObjs[data.LC].polygon){
                    var area = _this._getArea(data.LC);
                    _this._measureObjs[data.LC].area
                    pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度'+'<br/>'+area;
                }
            }
            oLabelObj.appendChild(pointText);
            _this._measureObjs[_this._lC].distance = lineDistance;
            _this._measureObjs[data.LC].markerObjs[i].label.setContent(oLabelObj);
        }
    },
    /**
     * 删除对应lC的测距
     */
    del: function(lC) {
        var _this = this;
        if (_this._measureObjs[lC]) {
            _this._measureGroup.removeLayer(_this._measureObjs[lC]);
            delete _this._measureObjs[lC];
            this._map.fire('measure-result',{
                LC:lC,
                action:"del"
            });
        }
    },
});

/**
 * 航向量算
 */
L.Util.getAngleByLatLng = function(startLong,startLat,endLong,endLat){
    startLong = parseFloat(startLong);
    startLat = parseFloat(startLat);
    endLong = parseFloat(endLong);
    endLat = parseFloat(endLat);
    var stsrtP = {
        x:startLong,
        y:startLat
    };
    var endP = {};
    endP.x=endLong;
    endP.y=endLat;

    var startPX_LatLongCoords = startLong;
    var startPY_LatLongCoords = startLat;
    var endPX_LatLongCoords = endLong;
    var endPY_LatLongCoords = endLat;

    var zhongjianX;
    var zhongjianY;
    zhongjianX = startPX_LatLongCoords > endPX_LatLongCoords ? startPX_LatLongCoords : endPX_LatLongCoords;
    zhongjianY = startPX_LatLongCoords > endPX_LatLongCoords ? startPY_LatLongCoords : endPY_LatLongCoords;
    var thirdX = zhongjianX;
    var thirdY = zhongjianY + 0.001;

    var prjParaPointC = {};
    prjParaPointC.x=thirdX;
    prjParaPointC.y=thirdY;

    stsrtP = L.Util.transformMercator(stsrtP);
    endP = L.Util.transformMercator(endP);
    var startPX = stsrtP.x;
    var startPY = stsrtP.y;
    var endPX = endP.x;
    var endPY = endP.y;

    prjParaPointC = L.Util.transformMercator(prjParaPointC);
    var objChangeCx = prjParaPointC.x;
    var objChangeCy = prjParaPointC.y; 

    //有三点计算角度，使用向量方法
    var mx, my, ax, ay, bx, by, ma_x, ma_y, mb_x, mb_y;
    mx = startPX_LatLongCoords > endPX_LatLongCoords ? startPX : endPX;
    my = startPX_LatLongCoords > endPX_LatLongCoords ? startPY : endPY;
    if (mx == startPX && my == startPY) {
        ax = endPX;
        ay = endPY;
    } else {
        ax = startPX;
        ay = startPY;
    }
    bx = objChangeCx;
    by = objChangeCy;
    ma_x = ax - mx;
    ma_y = ay - my;
    mb_x = bx - mx;
    mb_y = by - my;
    var v1 = (ma_x * mb_x) + (ma_y * mb_y);
    var ma_val = Math.sqrt(ma_x * ma_x + ma_y * ma_y);
    var mb_val = Math.sqrt(mb_x * mb_x + mb_y * mb_y);
    var cosM = v1 / (ma_val * mb_val);
    var angleAMB = Math.acos(cosM) * 180 / Math.PI;


    var xiangxian = 0; // 定义象限变量
    var lastAngle = 0;
    if ((endPY_LatLongCoords - startPY_LatLongCoords) > 0 && (endPX_LatLongCoords - startPX_LatLongCoords) == 0) {
        lastAngle = 0;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) == 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) > 0) {
        lastAngle = 90;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) < 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) == 0) {
        lastAngle = 180;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) == 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) < 0) {
        lastAngle = 270;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) > 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) > 0) {
        xiangxian = 1;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) > 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) < 0) {
        xiangxian = 2;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) < 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) < 0) {
        xiangxian = 3;
    } else if ((endPY_LatLongCoords - startPY_LatLongCoords) < 0
            && (endPX_LatLongCoords - startPX_LatLongCoords) > 0) {
        xiangxian = 4;
    };


    switch (xiangxian) {
    case 1:
        lastAngle = 180 - angleAMB;
        break;
    case 2:
        lastAngle = 360 - angleAMB;
        break;
    case 3:
        lastAngle = 360 - angleAMB;
        break;
    case 4:
        lastAngle = 180 - angleAMB;
        break;
    default:
        //alert("none");
    }

    return parseInt(Math.round(lastAngle));
}
/**
 * 经纬度转墨卡托
 */
L.Util.transformMercator =function(lonLat){
    var mercator = {};
    var x = lonLat.x * 20037508.34 / 180;
    var y = Math.log(Math.tan((90 + lonLat.y) * Math.PI / 360)) / (Math.PI / 180);
    y = y * 20037508.34 / 180;
    mercator.x = x;
    mercator.y = y;
    return mercator; 
};
/**
 * 墨卡托转经纬度
 */
 L.Util.transformMercator =function(lonLat){
     var mercator = {};
     var x = lonLat.x * 20037508.34 / 180;
     var y = Math.log(Math.tan((90 + lonLat.y) * Math.PI / 360)) / (Math.PI / 180);
     y = y * 20037508.34 / 180;
     mercator.x = x;
     mercator.y = y;
     return mercator;
 };
/**
 * 测量工具
 */
map2DViewer.measureToolFire = function(data) {
    console.log(data);
};
map2DViewer.setMeasureTool = function(options,map) {
    var defaultData = {
        action: 'add',
        position: 'topleft',
        offset: [10, 10],
        background: "#fff",
        color: "#000",
        font_size: "14px",
        closeButton: true
    }
    for(key in options){
        defaultData[key] = options[key];
    }
    switch (defaultData.action) {
        case 'add':
            this.measureTool = new L.Control.Measure({
                position: defaultData.position,
                offset: defaultData.offset,
                background: defaultData.background,
                color: defaultData.color,
                font_size: defaultData.font_size,
                closeButton: defaultData.closeButton
            }).addTo(map);
            map.on('measure-result', map2DViewer.measureToolFire);
            return this.distanceTool;
            break;
        case 'remove':
            map.off('measure-result', map2DViewer.measureToolFire);
            map.removeControl()
            break;
    }
}