import $ from 'jquery'
/**
 * 鹰眼及双屏联动工具
 */
class OverMapBar{
    _container= null;
    _mapAngle=0;
    _targetId="";
    _miniMap=null;
    _vectorLayer=null;
    _viewerMoving= false;
    _miniMapMoving= false;
    _isViewLink=false;
    _toggleDisplayButton=null;
    _minimized=false;
	_isScreen=false;
	_oldWidth='';
	_oldHeight='';
    viewer=null;
    tileLayer= null;
	pipeLayers=null;
    _tiandituType="";
    options={
        position: 'bottomleft',
        toggleDisplay: true,
        minimized: false,
		isScreen:false,
        parent:null,
        isViewLink:false,
        width: '150px',
        height: '150px',
        collapsedWidth: '19px',
        collapsedHeight: '19px',        
        strings: { hideText: '隐藏鹰眼', showText: '显示鹰眼' },
        mapOptions: {
            toggleDisplay: true,
            fillcolor: 'rgba(255,0,0,0.2)',
            strokecolor: 'rgba(255,0,0,1)',
            strokewidth:1
        }
    };

    /**
     * 构造函数
     */
    constructor(viewer, layer, options) {
        this.viewer = viewer;
        this.tileLayer = layer;
        this._container = options.container;
        this._targetId=options.targetId
        this.options=$.extend({},this.options,options);      
		this._isScreen=this.options.isScreen;
        this._isViewLink=this.options.isViewLink;
        this._initMap();        
    }

    /**
     * 分屏
     */
	splitScreen(options) {
		this._oldWidth=this.options.width;
		this._oldHeight=this.options.height;
		this.options.width=options.width;
		this.options.height=options.height;
        this._isViewLink=false;
		this._container.style.width = this.options.width;
        this._container.style.height = this.options.height;
        const overViewmap=this.options.parent;
        overViewmap.startLayerList();
        $(this._container).empty();	
        if(this._miniMap){
            this._miniMap.setTarget(null);
        }
		this._isScreen=true;		
		setTimeout(function () { 
			this.viewer.scene.camera.moveEnd._listeners=[];
			this.viewer.scene.camera.moveEnd._scopes=[];
			this.viewer.scene.camera.moveStart._listeners=[];
			this.viewer.scene.camera.moveStart._scopes=[];
			this._initMap();
            //切换分屏是初始化天地图
            if(this._tiandituType!==""){
                this.updateTianditu(this._tiandituType);
            }
        }.bind(this), 200);		
    }

    /**
     * 恢复到默认状态
     */
	restoreScreen(){
		this.options.width=this._oldWidth;
		this.options.height=this._oldHeight;
		this._container.style.width = this.options.width;
        this._container.style.height = this.options.height;
        this._mapAngle=this._getViewAngle();
		$(this._container).empty();	
        //关闭双屏开启鹰眼联动
        this._isViewLink=true;
		this._isScreen=false;		
		setTimeout(function () { 
			this.viewer.scene.camera.moveEnd._listeners=[];
			this.viewer.scene.camera.moveEnd._scopes=[];
			this.viewer.scene.camera.moveStart._listeners=[];
			this.viewer.scene.camera.moveStart._scopes=[];
			this._initMap();
            //切换分屏是初始化天地图
            if(this._tiandituType!==""){
                this.updateTianditu(this._tiandituType);
            }
        }.bind(this), 300);		
	}

    /**
     * 初始化地图
     */
    _initMap() {
            var _this = this;
            var that=this;
            this._container.style.width = this.options.width;
            this._container.style.height = this.options.height
            L.DomEvent.disableClickPropagation(_this._container);
            L.DomEvent.on(_this._container, 'mousewheel', L.DomEvent.stopPropagation);       

            var Drag = /*@__PURE__*/(function (PointerInteraction) {
                function Drag() {
                    PointerInteraction.call(this, {
                        handleDownEvent: handleDownEvent,
                        handleDragEvent: handleDragEvent,
                        handleMoveEvent: handleMoveEvent,
                        handleUpEvent: handleUpEvent
                    });
                    this.coordinate_ = null;
                    
                    this.cursor_ = 'pointer';
                    
                    this.feature_ = null;

                    
                    this.previousCursor_ = undefined;
                }

                if (PointerInteraction) 
                    Drag.__proto__ = PointerInteraction;
                Drag.prototype = Object.create(PointerInteraction && PointerInteraction.prototype);
                Drag.prototype.constructor = Drag;

                return Drag;
            }(ol.interaction.Pointer));
            
            //鼠标按下事件
            function handleDownEvent(evt) {
                var map = evt.map;
                var feature = map.forEachFeatureAtPixel(evt.pixel,
                    function (feature) {
                        return feature;
                    });
                if (feature) {
                    this.coordinate_ = evt.coordinate;
                    this.feature_ = feature;
                }
                return !!feature;
            }
            
            //鼠标拖动事件
            function handleDragEvent(evt) {
                var deltaX = evt.coordinate[0] - this.coordinate_[0];
                var deltaY = evt.coordinate[1] - this.coordinate_[1];
                var geometry = /** @type {ol.geom.SimpleGeometry} */
                    (this.feature_.getGeometry());
                geometry.translate(deltaX, deltaY);
                this.coordinate_[0] = evt.coordinate[0];
                this.coordinate_[1] = evt.coordinate[1];
            }
            
            //鼠标移动事件
            function handleMoveEvent(evt) {
                if (this.cursor_) {
                    var map = evt.map;
                    var feature = map.forEachFeatureAtPixel(evt.pixel,
                        function (feature) {
                            return feature;
                        });
                    var element = evt.map.getTargetElement();
                    if (feature) {
                        if (element.style.cursor != this.cursor_) {
                            this.previousCursor_ = element.style.cursor;
                            element.style.cursor = this.cursor_;
                        }
                    } else if (this.previousCursor_ !== undefined) {
                        element.style.cursor = this.previousCursor_;
                        this.previousCursor_ = undefined;
                    }
                }
            }

            //鼠标弹起、设置场景同步
            function handleUpEvent() {
                var testPolygon = new ol.geom.Polygon(this.feature_.getGeometry().getCoordinates());
                var tooltipCoord = testPolygon.getInteriorPoint().getCoordinates();//线的形成面的中间点
                if (!this._viewerMoving&&that._isViewLink) {
                    this._miniMapMoving = true;
                    var rect = this._isScreen?this.map_.getView().calculateExtent(this.map_.getSize()):testPolygon.getExtent();
                    var west = rect[0];
                    var east = rect[2];
                    var north = rect[3];
                    var south = rect[1];
                    var destination = Cesium.Rectangle.fromDegrees(west, south, east, north);
                    var centerPt=null;
                    centerPt=Cesium.Rectangle.center(destination, centerPt);
                    
                    var viewer = that.viewer;			
                    var camera = viewer.scene.camera;
                    var orientation = {
                        heading: camera.heading,
                        pitch:camera.pitch,
                        roll:camera.roll
                    };
                    that.viewer.scene.camera.setView({
                        destination: destination,
                        orientation: orientation
                    });
                } else {
                    this._viewerMoving = false;
                }
                this.coordinate_ = null;
                this.feature_ = null;
                return false;
            }

            //init map and layers
            _this._miniMap=new ol.Map({
                    interactions: ol.interaction.defaults().extend([new Drag()]),
                    controls: ol.control.defaults({
                        attribution: false,
                        zoom: false,
                    }),
                    layers: this._isScreen?this.tileLayer:[],
                    target: this._targetId,              
                    view: new ol.View({
                        projection: 'EPSG:4326',
                        rotation:this._isScreen?this._mapAngle:0
                    })
            });
           var extent = _this._getViewRange();
           if(extent && extent.length==4){
               extent=this._getZoomOutRange(extent);
           }
            _this._miniMap.getView().fit(extent, this._miniMap.getSize());
            if(_this.pipeLayers){
                for(var i=0;i<_this.pipeLayers.length;i++){
                    this._miniMap.addLayer(_this.pipeLayers[i]);
                }
            }
            _this._viewerMoving = true;
            _this._miniMapMoving = false;
            _this._minimized = false;
            _this._vectorLayer=null;
            if(this._isScreen == false){
                if (this.options.toggleDisplay) {
                    this._addToggleButton();
                }
                var coor = [[[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]];
                var polygonFeature = new ol.Feature(new ol.geom.Polygon(coor));
                var vectorSource = new ol.source.Vector({
                    features: [polygonFeature]
                });
                var op = _this.options.mapOptions;
                _this._vectorLayer = new ol.layer.Vector({
                        source: vectorSource,
                        style: new ol.style.Style({
                            fill: new ol.style.Fill({ color: op.fillcolor != undefined ? op.fillcolor : 'rgba(255,0,0,0.2)' }),
                            stroke: new ol.style.Stroke({
                                color: op.strokecolor != undefined ? op.strokecolor : 'red', width: op.strokewidth != undefined ? op.strokewidth : 1
                            })
                        })
                    });
                _this._miniMap.addLayer(_this._vectorLayer);
                setTimeout(function () {
                    if (_this.options.minimized == true)
                        _this._toggleDisplayButtonClicked();
                    _this._container.style.visibility = 'visible';                    
                }.bind(_this), 300);
            }
            _this._startEvents();
            
    }

    /**
     * 启动监听事件
     */
    _startEvents() {
        var _this=this;
        var camera = _this.viewer.scene.camera;				
		camera.moveEnd.addEventListener(_this._moveEnd.bind(_this));			
		camera.moveStart.addEventListener(_this._moveStart.bind(_this));

        _this._miniMap.on('pointermove', function (evt) {
                _this._miniMap.getTargetElement().style.cursor = 'pointer';
        }.bind(_this));
        _this._miniMap.on('click', function (e) {
            var coor = e.coordinate;
            //this._map.getView().setCenter(coor);
        }.bind(_this));

        _this._miniMap.on('moveend', _this._onMiniMapMoved.bind(_this));
    }

    /**
     * 场景摄像头移动结束
     */
	_moveEnd(e) {
        var _this = this;
        //关闭时停止刷新
        if(_this._minimized) return;       
		if(_this._miniMap){
            var extent = this._getViewRange();
            var coor = [[[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]];
            if (!_this._miniMapMoving&&this._isViewLink) {
                _this._viewerMoving = true;
                var view = _this._miniMap.getView();
                var ext=_this._getViewExtRange();
                if(extent && extent.length==4){
                     ext=_this._getZoomOutRange(extent);
                     coor=[[[ext[0], ext[1]], [ext[2], ext[1]], [ext[2], ext[3]], [ext[0], ext[3]], [ext[0], ext[1]]]];
                }
                if(_this._isScreen){
                     _this._miniMap.getView().fit(ext, this._miniMap.getSize());
                     _this._miniMap.getView().setRotation(_this._getViewAngle());                     
                }else{
                     _this._miniMap.getView().fit(_this._getViewExtRange(), this._miniMap.getSize());
                }
                 _this._miniMap.getView().setCenter(_this._getViewCenter(ext));               			
            } else {
                _this._miniMapMoving = false;
            }
            if(_this._vectorLayer){
                _this._vectorLayer.getSource().getFeatures()[0].getGeometry().setCoordinates(coor);
            }             
        }
    }

    /**
     * 场景摄像头开始移动
     */
	_moveStart (e) {
        var _this = this;
        //关闭时停止刷新
        if(_this._minimized) return;       
		if(_this._miniMap){
            var extent = this._getViewRange();
            if(extent && _this._vectorLayer){
                extent=_this._getZoomOutRange(extent);
                 var coor = [[[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]];
                 this._vectorLayer.getSource().getFeatures()[0].getGeometry().setCoordinates(coor);
            }
		}
    }

    /**
     * 地图移动完成
     */
    _onMiniMapMoved (e) {
         if (!this._viewerMoving&&!this._minimized&&this._isViewLink) {
            this._miniMapMoving = true;
            const camera = this.viewer.camera;
            let heading=this._miniMap.getView().getRotation();
            heading=heading/Math.PI*180;
            heading=(360-heading)/180*Math.PI;            
            camera.flyTo({
                destination: camera.position,
                orientation: {
                    heading: heading,
                    pitch: camera.pitch,
                    roll: camera.roll
                }
            });
            if(this._isScreen==true){
                    var rect =this._miniMap.getView().calculateExtent(this._miniMap.getSize());
                    var west = rect[0];
                    var east = rect[2];
                    var north = rect[3];
                    var south = rect[1];
                    var destination = Cesium.Rectangle.fromDegrees(west, south, east, north);                    
                    var viewer = this.viewer;
                    var orientation = {
                        heading: camera.heading,
                        pitch:camera.pitch,
                        roll:camera.roll
                    };
                    this.viewer.scene.camera.setView({
                        destination: destination,
                        orientation: orientation
                    });
            }
        } else {
            this._viewerMoving = false;
        }       
    }

    /**
     * 添加按钮
     */
    _addToggleButton () {
        this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
            '', this._toggleButtonInitialTitleText(), ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' +
                this.options.position), this._container, this._toggleDisplayButtonClicked, this) : undefined;        
        this._toggleDisplayButton.style.width = this.options.collapsedWidth;
        this._toggleDisplayButton.style.height = this.options.collapsedHeight;
    }

    /**
     * 按钮提示信息
     */
    _toggleButtonInitialTitleText () {
        if (this.options.minimized) {
            return this.options.strings.showText;
        } else {
            return this.options.strings.hideText;
        }
    }

    /**
     * 创建按钮
     */
    _createButton (html, title, className, container, fn, context) {
        var link = L.DomUtil.create('a', className, container);
        link.innerHTML = html;
        link.href = '#';
        link.title = title;
        var stop = L.DomEvent.stopPropagation;
        L.DomEvent
            .on(link, 'click', stop)
            .on(link, 'mousedown', stop)
            .on(link, 'dblclick', stop)
            .on(link, 'click', L.DomEvent.preventDefault)
            .on(link, 'click', fn, context);
        return link;
    }

    /**
     * 点击事件
     */
    _toggleDisplayButtonClicked () {
        if (!this._minimized) {
            this._minimize();
        } else {
            this._restore();
        }
    }

    /**
     * 最小化
     */
    _minimize () {
        if (this.options.toggleDisplay) {
            this._container.style.width = this.options.collapsedWidth;
            this._container.style.height = this.options.collapsedHeight;
            this._toggleDisplayButton.className += (' minimized-' + this.options.position);
            this._toggleDisplayButton.title = this.options.strings.showText;
        } else {
            this._container.style.display = 'none';
        }
        this._minimized = true;
		this.options.minimized=true;
        this._isViewLink=false;
        this._onToggle();
    }

    /**
     * 恢复正常
     */
    _restore () {
        if (this.options.toggleDisplay) {
            this._container.style.width = this.options.width;
            this._container.style.height = this.options.height;
            this._toggleDisplayButton.className = this._toggleDisplayButton.className
                .replace('minimized-' + this.options.position, '');
            this._toggleDisplayButton.title = this.options.strings.hideText;
        } else {
            this._container.style.display = 'block';
        }
        this._minimized = false;
        this._isViewLink=true;
		this.options.minimized=true;
        //this._initMap();
        this._onToggle();
        this._miniMap.updateSize();
    }
   
    _onToggle () {
        L.Util.requestAnimFrame(function () {
            L.DomEvent.on(this._container, 'transitionend', this._fireToggleEvents, this);
            if (!L.Browser.any3d) {
                L.Util.requestAnimFrame(this._fireToggleEvents, this);
            }
        }, this);
    }

    _fireToggleEvents () {
        L.DomEvent.off(this._container, 'transitionend', this._fireToggleEvents, this);
    }

    /**
     * 获取场景边界给二维视图
     */
    _getViewRange () {
        var viewer = this.viewer;
		var bounds=null;
		if(viewer){
			var camera = viewer.scene.camera;
			var range = camera.computeViewRectangle();
			if(camera && range){
				var west=undefined,east=undefined,north=undefined,south=undefined;
				if(range.west !=undefined)
				   west = range.west / Math.PI * 180;
				if(range.east !=undefined)
				   east = range.east / Math.PI * 180;
				if(range.north !=undefined)
				   north = range.north / Math.PI * 180;
				if(range.south !=undefined)
				   south = range.south / Math.PI * 180;
				if(west!=undefined && east!=undefined && north!=undefined && south!=undefined)
					bounds = [west, south,east, north];
			}	
		}       
        return bounds;
    }

    /**
     * 计算视图范围
     */
    _getZoomOutRange(rect) {
            var west = rect[0];
            var east = rect[2];
            var north = rect[3];
            var south = rect[1];
            if (this._isScreen == false) {
                var factor = 2.0;
                var xdis = Math.abs(east - west);
                var ydis = Math.abs(north - south);
                var xoff = xdis * (factor - 1) / 10.0;
                var yoff = ydis * (factor - 1) / 10.0;
                west -= xoff;
                east += xoff;
                north += yoff;
                south -= yoff;
                
            }
            else {
                var viewer = this.viewer;
                var camera = viewer.scene.camera;
                var cartographic = Cesium.Cartographic.fromCartesian(camera.position);
                var altitude = cartographic.height;
                var longitude = Cesium.Math.toDegrees(cartographic.longitude);
                var latitude = Cesium.Math.toDegrees(cartographic.latitude);
                var size = this._calculateSizeFromAltitude(altitude);
                size = size * 0.2;
                west = longitude - size;
                east = longitude + size;
                north = latitude + size;
                south = latitude - size;
            }
            if (west < -180) {
                west = -180;
            }
            if (east > 180) {
                east = 180;
            }
            if (north > 90) {
                north = 90;
            }
            if (south < -90) {
                south = -90;
            }
            var bounds = [west, south, east, north];
            return bounds;
    }

    /// <summary>
	/// 根据给定的场景高度计算地图中显示范围的宽度
	/// </summary>
	/// <param name="altitude">场景高度</param>
	/// <returns>地图显示范围尺寸</returns>
	_calculateSizeFromAltitude(altitude) {
		var _PI = 3.1415926;
		var _earthRadius = 6378137;
		var size;
		if (altitude >= _earthRadius) {//当场景高度大于可全幅显示整球的高度时
			var ratio = (altitude + _earthRadius) * 0.5;
			size = 120 * ratio / _earthRadius
		}
		else {//当场景高度小于可全幅显示整球的高度时，即无法看到整球时
			var tan30 = Math.tan(_PI / 6);
			//设置方程组的a,b,c
			var a = (Math.pow(tan30, 2) + 1) * Math.pow(_earthRadius, 2);
			var b = -2 * (_earthRadius + altitude) * _earthRadius * Math.pow(tan30, 2);
			var c = Math.pow(tan30, 2) * Math.pow(_earthRadius + altitude, 2) - Math.pow(_earthRadius, 2.0);
			//解一元二次方程，取锐角，因此余弦值较大
			var cosd = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a);
			var d = Math.acos(cosd);
			var widthd = 2 * d * _earthRadius;
			size = (widthd / (_PI * _earthRadius)) * 180;
		}
		return size;
	}

    /**
     * 扩大范围
     */
    _getViewExtRange(){
        var bounds=this._getViewRange();
        var extbounds=null;
        if(bounds){
            extbounds=[];
            for(var i=0;i<bounds.length;i++){
                extbounds.push(bounds[i]*3.0);
            }
        }
        return extbounds;
    }

    /**
     * 获取中心点坐标
     */
    _getViewCenter (bounds) {        
        var center=null;
		if(bounds && bounds.length==4){
			 center=[(bounds[0]+bounds[2])/2.0,(bounds[1]+bounds[3])/2.0]
		}       
        return center;
    }

    /**
     * 获取与正北方向的夹角
     */
    _getViewAngle(){
        var viewer=this.viewer;
        var angle=0;
        if(viewer){
            var camera = viewer.scene.camera;
            angle =Math.abs(Cesium.Math.toDegrees(camera.heading));
            angle=(360-angle)/180.0*Math.PI;
        }
        return angle;        
    }

    /**
     * 增加管网图层
     */
    addPipeLayers (pipeLayers) {
        if(pipeLayers){
            for(var i=0;i<pipeLayers.length;i++){
                this._miniMap.addLayer(pipeLayers[i]);
            }
        }
        this.pipeLayers=pipeLayers;
    }  
    /**
     * 该方法用于与天地图切换联动
     * @param layerType 
     */
     updateTianditu(layerType,isLable=true){
         layerType=layerType.split('_')[0];
        const token="908404235938aecd5826e630a95c88b0";
        const miniMap=this._miniMap;
        const layers=miniMap.getLayers();
        //删除天地图
        layers.array_.forEach(layer=>{
            if(layer.values_&&(layer.values_.credit==="tianditu_base"||layer.values_.credit==="tianditu_poi")){
                miniMap.removeLayer(layer)
            }
        })
        //加载天地图
        const baselayer=new ol.layer.Tile({
            source: new ol.source.Tianditu({
                url:"http://t{0-7}.tianditu.gov.cn/{layer}_{proj}/wmts?",
                layerType: layerType,
                key: token,
                projection: "EPSG:4326"
            }),
            credit: "tianditu_base"
        });
        const poilayer=new ol.layer.Tile({
            source: new ol.source.Tianditu({
                url:"http://t{0-7}.tianditu.gov.cn/{layer}_{proj}/wmts?",
                layerType: layerType,
                key: token,
                isLabel: isLable,
                projection: "EPSG:4326"
            }),
            credit: "tianditu_poi"
        });
        layers.insertAt(0,baselayer);
        layers.insertAt(1,poilayer);
        this._tiandituType=layerType;
    } 
}
export default OverMapBar;