import 'ol/ol.css'
import '@/assets/map/popup.css'
import { Tile, Image } from 'ol/layer';
import { XYZ, TileWMS, ImageWMS } from 'ol/source';
import LayerVector from 'ol/layer/Vector';
import SourceVector from 'ol/source/Vector';
import { Map, View, Feature, Overlay } from 'ol';
import { fromLonLat, transform } from 'ol/proj';
import { defaults, FullScreen, ScaleLine, ZoomToExtent, ZoomSlider, MousePosition } from 'ol/control'
import { Point } from 'ol/geom';
import { Style, Icon, Text, Fill, Stroke, Circle } from 'ol/style';
import { createStringXY, format } from 'ol/coordinate';
import { getCenter } from 'ol/extent';
import { METERS_PER_UNIT } from 'ol/proj/Units';
import { labelZoomSize, colorRGBtoHex } from "@/assets/map/maptool";
import { Draw } from 'ol/interaction';



//使用export输出OLMap类
export class OLMap {
    /**构造函数，初始化地图对象 */
    constructor(divId) {
        this.mapId = divId;
        this.map = new Map({
            target: this.mapId,  // 地图目标容器
            controls: defaults().extend([new ScaleLine()]), //添加默认控件，并拓展比例尺控件
        });

        //监听地图鼠标移动事件，改变鼠标指针样式
        this.map.on('pointermove', function (evt) {
            var pixel = this.getEventPixel(evt.originalEvent);
            var hit = this.hasFeatureAtPixel(pixel);
            var element = this.getTargetElement();
            element.style.cursor = hit ? 'pointer' : 'move';
        });
        this.view = this.map.getView();
        this.zoomMin = 4;
        this.zoomMax = 20;
    }
    //静态变量，保存当前的地图和视图对象
    static mapObj = this.map;
    static viewObj = this.view;
    //移除地图上的控制组件
    removeControl(control) {
        this.map.removeControl(control);
    }
    //设置地图缩放范围
    setZoomRange(zoomMin, zoomMax) {
        this.setMaxZoom(zoomMax);
        this.setMinZoom(zoomMin);
    }
// 获取地图视图对象
    getView() {
        return this.map.getView();
    }
    // 获取地图对象
    getMap() {
        return this.map;
    }

// 1 添加卫星地图层
    addMapWX(isVisible) {
        var wxMap = new Tile({
            id: 'map_wx',
            name: "卫星地图",
            source: new XYZ({
                url: 'http://192.168.196.204/v1.0/gr?x={x}&y={y}&z={z}', //卫星地图
                //url: 'http://t1.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=49ea1deec0ffd88ef13a3f69987e9a63',//天地图影像
                wrapX: false
            }),
            type: 'wxmap'
        });
        wxMap.setVisible(isVisible);
        this.map.addLayer(wxMap);
    }

// 2 添加带标注的卫星地图层
    addMapWXTag(isVisible) {
        var wxMap = new Tile({
            id: 'map_wxtag',
            name: "卫星地图标注",
            source: new XYZ ({
                url: 'http://192.168.196.204/v1.0/go?x={x}&y={y}&z={z}', //道路及兴趣点标注
                //url: 'http://t1.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=49ea1deec0ffd88ef13a3f69987e9a63',//天地图注记
                wrapX: false
            }),
            type: 'wxmap'
        });
        wxMap.setVisible(isVisible);
        this.map.addLayer(wxMap);
    }

 // 添加ArcGIS地图层
    addMapArcgis() {
        var arcgisMap = new Tile({
            id: 'map_arcgis',
            name: "ArcGIS地图",
            source: new XYZ({
                url: "https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}",
                wrapX: false
            }),
            type: 'arcgismap'
        });
        this.map.addLayer(arcgisMap);
    }
// 添加WMS瓦片地图层
    addMapTileWMS(layerId, url, params, minZoom = 0, maxZoom = 15) {
        //采用瓦片地图WMS服务容易造成瓦片标注缺失或重叠问题
        var tiled = new Tile({
            id: layerId,
            name: 'WMS瓦片地图',
            visible: params.visible ? true : false,
            source: new TileWMS({
                url: url,
                params: {
                    'FORMAT': 'image/png',
                    'VERSION': '1.1.1',
                    tiled: true,
                    "STYLES": !params.styles ? '' : params.styles,
                    "LAYERS": !params.layers ? '' : params.layers,
                    "exceptions": 'application/vnd.ogc.se_inimage',
                }
            }),
            type: 'basemap'
        });
        this.map.addLayer(tiled);
        var view = this.map.getView();
        view.on('change:resolution', function (evt) {
            var resolution = evt.target.get('resolution'); //分辨率: 每个象元代表的实地距离
            var z = view.getZoom();
            if (z >= minZoom && z <= maxZoom) {
                tiled.setVisible(true);
            } else {
                tiled.setVisible(false);
            }
        });
    }
// 添加WMS图像地图层 注释无妨碍显示
    addMapImageWMS(layerId, url, params, minZoom = 0, maxZoom = 15) {
        //采用图像WMS服务以视图范围整体作为请求参数，避免瓦片标注缺失或重叠问题
        var view = this.map.getView();
        var region;
        if (!params.bbox) {
            var extent = view.calculateExtent(this.map.getSize());
            var p1 = this.geoFromMrc([extent[0], extent[1]]);
            var p2 = this.geoFromMrc([extent[2], extent[3]]);
            var srs = view.getProjection().getCode();
            region = [p1[0], p1[1], p2[0], p2[1]];
        }
        //console.log('extent: '+region);
        //console.log('bbox: '+params.bbox);
        var untiled = new Image({
            id: layerId,
            name: 'WMS图像地图',
            visible: params.visible ? true : false,
            source: new ImageWMS({
                ratio: 1,
                url: url,
                params: {
                    'FORMAT': 'image/png',
                    'VERSION': '1.1.1',
                    "STYLES": !params.styles ? '' : params.styles,
                    "LAYERS": !params.layers ? '' : params.layers,
                    'BBOX': !params.bbox ? region : params.bbox,
                    "exceptions": 'application/vnd.ogc.se_inimage',
                }
            }),
            type: 'basemap'
        });
        this.map.addLayer(untiled);
        var wmsFlag = this.wmsFlag;
        view.on('change:resolution', function (evt) {
            var resolution = evt.target.get('resolution'); //分辨率: 每个象元代表的实地距离
            var z = view.getZoom();
            if (z >= minZoom && z <= maxZoom) {
                untiled.setVisible(true);
            } else {
                untiled.setVisible(false);
            }
        });
    }
    // 添加WMS图像地图层 注释无妨碍显示
    rmBaseMapLayers() { //清除基础地图
        var layers = this.map.getLayers().getArray().slice();
        //此处必需使用 getArray()和 slice() (复制引用数组)来避免map.removeLayer()删除失败
        //map.removeLayer()操作将更改map的layers
        for (let i = 0; i < layers.length; i++) {
            let layer = layers[i];
            if (layer.get('type') == 'basemap') {
                this.map.removeLayer(layer);
            }
        }
    }
    // 移除所有的标记和弹出窗口  rmOverlays rmOverlaysById移除地图上特定标记或弹出窗口 注释无妨碍显示
    rmOverlays(types = ['marker', 'label', 'popup', 'pin', 'tag', '$marker', '$text']) {//清除所有Marker和Popup
        var layers = this.map.getOverlays().getArray().slice();
        //console.log('overlays length before: '+layers.length);
        var overlays = [];
        for (let i = 0; i < layers.length; i++) {
            const layer = layers[i];
            let oid = layer.getId();
            for (let i in types) {
                if (oid.indexOf(types[i]) >= 0) {
                    overlays.push(layer);
                }
            }
        }
        for (let i in overlays) {
            this.map.removeOverlay(overlays[i]);
        }
        layers = this.map.getOverlays().getArray().slice();
        //console.log('overlays length after: '+layers.length);
    }
    // 根据ID移除特定的标记或弹出窗口
    rmOverlaysById(types = ['marker', 'label', 'popup', 'pin', 'tag', '$marker', '$text'], id) {//清除所有Marker和Popup
        var layers = this.map.getOverlays().getArray().slice();
        //console.log('overlays length before: '+layers.length);
        var overlays = [];
        for (let i = 0; i < layers.length; i++) {
            const layer = layers[i];
            let oid = layer.getId();
            for (let i in types) {
                //console.log(oid,types[i], id);
                if (oid == (types[i] + '_' + id)) {
                    overlays.push(layer);
                }
            }
        }
        for (let i in overlays) {
            this.map.removeOverlay(overlays[i]);
        }
        layers = this.map.getOverlays().getArray().slice();
        //console.log('overlays length after: '+layers.length);
    }

    setViewXY([x, y], scale) {
        //[x,y]为投影坐标系下视图的中心点坐标
        var view = new View({
            center: [x, y],
            zoom: scale,
            projection: 'EPSG:3857', //设置墨卡托投影坐标系
            minZoom: this.zoomMin,
            enableRotation: false, //禁止地图旋转
        });
        this.map.setView(view);
    }

    setView([lon, lat], scale) {
        //[lon,lat]为地理坐标系下的中心点坐标
        var cp = fromLonLat([lon, lat]); //将地理坐标转为投影坐标
        var view = new View({
            center: cp,
            zoom: scale,
            projection: 'EPSG:3857', //设置墨卡托投影坐标系
            minZoom: this.zoomMin,
            enableRotation: false, //禁止地图旋转
        });
        this.map.setView(view);
    }

    setViewDefault() { //缺省条件显示南通地区范围
        var cp = fromLonLat([121, 32]); //将地理坐标转为投影坐标
        this.setViewXY(cp, 8);
    }

    setViewChina(zoomNow = 3.7) { //显示中国范围
        var cp = fromLonLat([109, 32]); //将地理坐标转为投影坐标
        this.setViewXY(cp, zoomNow);
        this.setMinZoom(this.zoomMin); //3.7
        this.setMaxZoom(this.zoomMax); //20
        //this.addCapital(0,4);

    }

    addCapital(minZoom = 1, maxZoom = 4) {
        var beijing = [116.395, 39.918];
        let labelPoint = fromLonLat(beijing); //将地理坐标转为投影坐标
        var labelFeature = new Feature({
            geometry: new Point(labelPoint),
            id: "cap_北京",
            name: '北京',
            type: 'label',
        });
        //矢量标注的数据源
        var vectorSource = new SourceVector({
            features: [labelFeature]
        });
        //矢量标注图层
        var vectorLayer = new LayerVector({
            id: 'capital',
            source: vectorSource,
            type: 'basemap'
        });
        this.map.addLayer(vectorLayer);
        //设置标注的尺寸
        var _style = new Style({
            image: new Icon(
                ({
                    anchor: [25, 20],
                    anchorOrigin: 'bottom-left',
                    anchorXUnits: 'pixels',
                    anchorYUnits: 'pixels',
                    offsetOrigin: 'top-right',
                    // offset:[0,10],
                    scale: 0.75, //图标缩放比例
                    opacity: 0.75, //透明度
                    src: require('@/assets/map/img/star.png') //图标的url
                })),
            text: new Text({
                textAlign: 'center', //位置
                textBaseline: 'middle', //基准线
                font: 'bolder 14px 微软雅黑', //文字样式
                text: labelFeature.get('name'),  //文本内容
                //文本填充样式（即文字颜色）
                fill: new Fill({ color: '#000000' }),
                stroke: new Stroke({ color: '#FFF', width: 1 }),
            }),
            zIndex: 9000,
        });
        labelFeature.setStyle(_style);
        var view = this.map.getView();
        view.on('change:resolution', function (evt) {
            var resolution = evt.target.get('resolution'); //分辨率: 每个象元代表的实地距离
            var z = view.getZoom();
            if (z >= minZoom && z <= maxZoom) {
                _style.getImage().setOpacity(0.75);
                _style.getImage().setScale(0.75);
                _style.getText().setFont('bolder 14px 微软雅黑');
            } else {
                _style.getImage().setOpacity(0);
                _style.getImage().setScale(0);
                _style.getText().setFont('bolder 0px 微软雅黑');
            }
            labelFeature.setStyle(_style);
        });
    }

    showMousePos(mposId = '', placeholder = '') { //显示视图中鼠标的经纬度
        //显示坐标
        var mpos;
        var mposObj = document.getElementById(mposId);
        if (mposId != '') {
            mpos = new MousePosition({
                className: 'custom-mouse-position',
                target: mposObj,
                //coordinateFormat: createStringXY(4),
                coordinateFormat: function (coordinate) {
                    return format(coordinate, '经度: {x}，纬度: {y}', 4);
                },
                placeholder: placeholder, //占位符
            });
        } else {
            mpos = new MousePosition({ coordinateFormat: createStringXY(4) });
        }
        mpos.setProjection("EPSG:4326");

        this.map.addControl(mpos);
        return mpos;
    }

    showZoom(zoomId = '', map = this.map) { //显示视图中的缩放级别
        var view = map.getView();
        var zoomObj = document.getElementById(zoomId);
        zoomObj.innerHTML = "缩放级别：" + view.getZoom().toFixed(1);
        view.on('change:resolution', function (evt) {
            //var resolution = evt.target.get('resolution'); //分辨率: 每个象元代表的实地距离
            //var resolution = view.getResolution();
            var zoom = view.getZoom();
            zoom = zoom.toFixed(1);
            //console.log("当前缩放级别："+zoom);
            if (zoomId == "") {
                if (document.getElementById('me_zoom')) {
                    document.getElementById('me_zoom').innerHTML = "缩放级别：" + zoom;
                } else {
                    let divScale = document.createElement('div');
                    divScale.setAttribute("id", "me_zoom");
                    divScale.innerHTML = "缩放级别：" + zoom;
                    document.body.appendChild(divScale);
                }
            } else {
                zoomObj.innerHTML = "缩放级别：" + zoom;
            }
        });
    }


    setViewByExtent(extent) {
        //extent: [minx, miny, maxx, maxy]
        //extent:[115, 30, 120, 32], 左下点[115,30], 右上点[120,32]
        var lb = [extent[0], extent[1]];
        var ru = [extent[2], extent[3]];
        var lb = fromLonLat(lb); //将地理坐标转为投影坐标
        var ru = fromLonLat(ru); //将地理坐标转为投影坐标
        var cds = [lb[0], lb[1], ru[0], ru[1]];
        //console.log(cds);
        this.setViewByExtentXY(cds);
    }

    setViewByExtentXY(extent) {
        //extent: [minx, miny, maxx, maxy]
        //extent:[13260344.548525335, 3654173.497931803, 13377876.802341036, 3770407.209894539], 左下点[13260344.548525335, 3654173.497931803], 右上点[13377876.802341036, 3770407.209894539]
        var lb = [extent[0], extent[1]];
        var ru = [extent[2], extent[3]];
        var cds = [lb[0], lb[1], ru[0], ru[1]];
        //console.log(cds);
        //添加全局视图控件
        var ctrl_extent = new ZoomToExtent({
            extent: cds,
            tipLabel: '显示初始范围',
            label: 'E'
        });
        this.map.addControl(ctrl_extent);
        //缩放地图到全局范围显示
        var view = this.map.getView();
        var r = view.getResolutionForExtent(cds, this.map.getSize());
        view.setResolution(r);
        view.setCenter(getCenter(cds));
    }

    getExtentCenterXY(extent) { //返回中心点XY坐标
        //extent: [minx, miny, maxx, maxy]
        //extent:[115, 30, 120, 32], 左下点[115,30], 右上点[120,32]
        var lb = [extent[0], extent[1]];
        var ru = [extent[2], extent[3]];
        var lb = fromLonLat(lb); //将地理坐标转为投影坐标
        var ru = fromLonLat(ru); //将地理坐标转为投影坐标
        var cds = [lb[0], lb[1], ru[0], ru[1]];
        return getCenter(cds);
    }

    getExtentCenter(extent) { //返回中心点地理坐标
        //extent: [minx, miny, maxx, maxy]
        //extent:[115, 30, 120, 32], 左下点[115,30], 右上点[120,32]
        var lb = [extent[0], extent[1]];
        var ru = [extent[2], extent[3]];
        var cds = [lb[0], lb[1], ru[0], ru[1]];
        return getCenter(cds);
    }

    getExtent() {
        var view = this.map.getView();
        var extent = view.calculateExtent(this.map.getSize());
        var p1 = this.geoFromMrc([extent[0], extent[1]]);
        var p2 = this.geoFromMrc([extent[2], extent[3]]);
        var region = [p1[0], p1[1], p2[0], p2[1]];
        return region;
    }

    setMinZoom(z) {
        //z=5
        var view = this.map.getView()
        view.setMinZoom(z);
        this.zoomMin = z;
    }

    setMaxZoom(z) {
        //z=5
        var view = this.map.getView()
        view.setMaxZoom(z);
        this.zoomMax = z;
    }

    setZoom(z) {
        //z=5
        var view = this.map.getView()
        view.setZoom(z);
    }

    geoToMrc([lon, lat]) {
        //transform geographic coordinate system  to Mercator projection CS
        //[lon,lat]->[x,y]
        return transform([lon, lat], 'EPSG:4326', 'EPSG:3857');
    }
    geoFromMrc([x, y]) {
        //transform Mercator projection coordinate system to geographic CS
        //[x,y]->[lon,lat]
        return transform([x, y], 'EPSG:3857', 'EPSG:4326');
    }

    degreeToMeter(deg) {
        return transform([deg, deg], 'EPSG:4326', 'EPSG:3857')[0];
    }

    degreeFromMeter(met) {
        return transform([met, met], 'EPSG:3857', 'EPSG:4326')[0];
    }

    zoomOut() {
        var view = this.map.getView();
        var zoom = view.getZoom();
        console.log("当前放大级别：" + zoom);
        view.setZoom(zoom - 1);
    }

    zoomIn = function () {
        var view = this.map.getView();
        var zoom = view.getZoom();
        console.log("当前缩小级别：" + zoom);
        view.setZoom(zoom + 1);
    }

    panTo([lon, lat]) {
        //[lon,lat]:[121,32]
        //获取地图视图
        var view = this.map.getView();
        var wh = fromLonLat([lon, lat]); //将地理坐标转为投影坐标
        //平移地图
        view.setCenter(wh);
        var zoom = view.getZoom();
        view.setZoom(zoom);
    }

    panToXY([X, Y], z = 10) {
        //[x,y]:[12100,3200]
        //获取地图视图
        var view = this.map.getView();
        //平移地图
        view.setCenter([X, Y]);
        var zoom = view.getZoom();
        zoom = z > zoom ? z : zoom;
        view.setZoom(zoom);
    }

    getZoom() {
        var view = this.map.getView();
        var zoom = view.getZoom();
        return zoom;
    }

    showScale(scaleId = "") {
        var view = this.map.getView();
        view.on('change:resolution', function (evt) {
            //var resolution = evt.target.get('resolution'); //分辨率: 每个象元代表的实地距离
            var resolution = viewObj.getResolution();
            var units = viewObj.getProjection().getUnits(); //default: m
            //console.log('units: '+units);
            var dpi = 25.4 / 0.28;
            var mpu = METERS_PER_UNIT[units]; //获取以米为单位的半径(如degrees，radians，pixels)，如果是m， mpu=1
            //console.log('mpu: '+mpu);

            const inchesPerMeter = 1000 / 25.4;  //每米多少英寸, 39.37
            var scale = resolution * mpu * inchesPerMeter * dpi; //比例尺: 图上距离和实地距离之比

            scale = Math.round(scale);
            if (scaleId == "") {
                if (document.getElementById('me_scale')) {
                    document.getElementById('me_scale').innerHTML = "比例尺 = 1 : " + scale;
                } else {
                    let divScale = document.createElement('div');
                    divScale.setAttribute("id", "me_scale");
                    divScale.innerHTML = "比例尺 = 1 : " + scale;
                    document.body.appendChild(divScale);
                }
            } else {
                document.getElementById(scaleId).innerHTML = "比例尺 = 1 : " + scale;
            }
        });
    }

    markerIsExist([lon, lat], tol = 0.01) {//根据坐标判断是否存在重复点
        var pt = fromLonLat([lon, lat]);//将地理坐标转为投影坐标
        //console.log(pt[0]);
        var overlays = this.map.getOverlays().getArray();
        for (var k in overlays) {
            let oid = overlays[k].getId();
            let ediv = overlays[k].get('element');
            let params = JSON.parse(ediv.getAttribute("desc"));
            let id = params.id;
            let name = params.name;
            if (oid.indexOf('marker') >= 0) {
                //let pos = overlays[k].getPosition();
                let pos = params.pos;
                let dis = ((pt[0] - pos[0]) ** 2 + (pt[1] - pos[1]) ** 2) ** 0.5;
                if (dis <= tol) {
                    return true;
                }
            }
        }
        return false;
    }

    markerIsExistById(id) {//根据id判断是否存在重复点
        var overlays = this.map.getOverlays().getArray();
        //console.log("markerIsExistById: "+id+", "+overlays.length);
        for (var k in overlays) {
            let oid = overlays[k].getId();
            let ediv = overlays[k].get('element');
            let params = JSON.parse(ediv.getAttribute("desc"));
            //console.log("markerIsExistById: "+oid+"，"+id);
            if (oid == ('marker_'+id)) {
                    return true;
            }
        }
        return false;
    }

    addMarkerAndLabel([lon, lat], id, label, fcolor = '#F00', opacity = 1, markerParams = {}, markerStyle = { width: '8px', height: '8px' }, func) {
        var cpoint = fromLonLat([lon, lat]);//将地理坐标转为投影坐标
        var map = this.map;
        //新增div元素
        var elementDiv = document.createElement('div'); //Marker
        elementDiv.className = "ol-marker";
        elementDiv.style.setProperty('background-color', fcolor);
        elementDiv.style.setProperty('opacity', opacity);
        elementDiv.style.setProperty('border', '1px solid' + fcolor);
        elementDiv.style.setProperty('width', markerStyle.width);
        elementDiv.style.setProperty('height', markerStyle.height);
        elementDiv.setAttribute('desc', JSON.stringify(markerParams));
        elementDiv.onclick = function (e) {
            //去除所有Popup
            var overlays = map.getOverlays().getArray();
            for (var k in overlays) { //恢复原marker样式
                let oid = overlays[k].getId();
                if (oid.indexOf('marker') >= 0) {
                    let e = overlays[k].get('element');
                    let c = e.style['background-color'];
                    //console.log('marker c0='+c);
                    c = colorRGBtoHex(c);
                    //console.log('marker c1='+c);
                    e.style.setProperty('border', '1px solid' + c);
                    //console.log('MarkerZ=' + overlays[k].get('element').style['z-index']);
                }
            }
            for (var k in overlays) {
                let oid = overlays[k].getId();
                if (oid.indexOf("popup") >= 0) {
                    overlays[k].setPosition(undefined); //隐藏所有POPUP
                }
            }
            //console.log(overlays.length);
            for (var k in overlays) {
                let a = overlays[k].getId();
                let a0 = a.split('_')[0];
                let a1 = a.split('_')[1];
                if (a1 == id && a0 == "popup") {
                    //overlays[k].setPosition(cpoint);  //设置为当前站点位置
                    //overlays[k].get('element').style.setProperty('z-index', 9000);
                    //console.log('POPUPZ=' + overlays[k].get('element').style['z-index']);
                    func(id, overlays[k], cpoint);
                    break;
                }
            }
            //高亮显示当前元素
            elementDiv.style.setProperty('border', '3px solid #FF0000');
        }

        //新增a元素
        var elementA = document.createElement("div"); //Label
        elementA.className = "ol-marker-text";
        elementA.style.setProperty('font-size', '0px');
        elementA.innerHTML = label; //设置文本
        elementA.setAttribute('desc', JSON.stringify(markerParams));
        elementA.onclick = function (e) {
            //去除所有Popup
            var overlays = map.getOverlays().getArray();
            for (var k in overlays) { //恢复原marker样式
                let oid = overlays[k].getId();
                if (oid.indexOf('marker') >= 0) {
                    let e = overlays[k].get('element');
                    let c = e.style['background-color'];
                    c = colorRGBtoHex(c);
                    //console.log('c='+c);
                    e.style.setProperty('border', '1px solid' + c);
                    //e.style.setProperty('z-index', 1000);
                }
            }
            for (var k in overlays) {
                let oid = overlays[k].getId();
                if (oid.indexOf("popup") >= 0) {
                    overlays[k].setPosition(undefined); //隐藏所有POPUP
                }
            }
            for (var k in overlays) {
                let a = overlays[k].getId();
                let a0 = a.split('_')[0];
                let a1 = a.split('_')[1];
                if (a1 == id && a0 == "popup") {
                    //overlays[k].setPosition(cpoint);  //设置为当前站点位置
                    //overlays[k].get('element').style.setProperty('z-index', 9000);
                    func(id, overlays[k], cpoint);
                    break;
                }
            }
            //高亮显示当前元素
            elementDiv.style.setProperty('border', '3px solid #FF0000');
        }
        // 新建的div元素添加a子节点
        elementDiv.appendChild(elementA);

        //实例化图文标注（图形+文本），添加到地图容器中
        var newMarker = new Overlay({
            id: "$marker_" + id,  //图钉
            name: label,
            position: cpoint,
            positioning: 'center-center',
            element: elementDiv,
            stopEvent: false //为了不遮盖popup，该处stopEvent必须设置为false
        });
        this.map.addOverlay(newMarker);

        var newText = new Overlay({
            id: "$text_" + id, //图钉文本
            name: label,
            position: cpoint,
            element: elementA,
            stopEvent: false, //为了不遮盖popup，该处stopEvent必须设置为false
            className: 'ol-marker-text-container'
        });
        this.map.addOverlay(newText);
    }
    // 用于在地图上添加标记（marker） 可自定义图标 位置 大小等属性
    addMarker([lon, lat], id, label, fcolor = '#F00', opacity = 1,
        markerParams = {},
        markerStyle = { width: '10px', height: '10px' },
        func, funcJggChang) {
        var cpoint = fromLonLat([lon, lat]);//将地理坐标转为投影坐标
        var map = this.map;
        //新增div元素
        var elementDiv = document.createElement('div'); //Marker
        elementDiv.className = "ol-marker";
        elementDiv.style.setProperty('background-color', fcolor);
        elementDiv.style.setProperty('opacity', opacity);
        elementDiv.style.setProperty('border', '1px solid #FFF');
        elementDiv.style.setProperty('width', markerStyle.width);
        elementDiv.style.setProperty('height', markerStyle.height);
        let prefix = 'marker_';
        markerParams.prefix = prefix;
        elementDiv.setAttribute('desc', JSON.stringify(markerParams));
        var geoToMrc = this.geoToMrc;
        elementDiv.onclick = function (e) { //点击当前Marker事件
            var overlays = map.getOverlays().getArray();
            let popup_display = [];//过滤已打开弹窗的站点
            for (let k in overlays) {
                let oid = overlays[k].getId();
                let ep = overlays[k].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let fid = params.id;
                if (oid.indexOf("popup") >= 0) {
                    if (oid == ('popup_' + id)) { //当前站点
                        //overlays[k].setPosition(cpoint);  //设置为当前站点位置
                        //overlays[k].get('element').style.setProperty('z-index', 9000);
                        //console.log('POPUPZ=' + overlays[k].get('element').style['z-index']);
                        //func(id, overlays[k], cpoint);
                        func(elementDiv, id, overlays[k]); //显示当前站点弹窗
                    } else {
                        if (params.display) { //记录其他打开弹窗的站点
                            popup_display.push(fid);
                        }
                        //overlays[k].setPosition(undefined); //隐藏其他站点POPUP
                    }
                }
            }
            /////////////////////////////////////////////////////////////////
            //隐藏当前的MarkerLabel
            for (let k in overlays) {
                let oid = overlays[k].getId();
                let ep = overlays[k].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let fid = params.id;
                if (oid.indexOf("label_") >= 0) { //关闭当前站点的label
                    let ep = overlays[k].get('element');
                    let params = JSON.parse(ep.getAttribute("desc"));
                    let pos = geoToMrc(params.pos);
                    let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
                    if (oid == ("label_" + id)) { //关闭当前站点的label
                        overlays[k].setPosition(undefined);
                        params.display = false;
                    } else if (popup_display.includes(fid)) { //关闭其他打开弹窗的label
                        overlays[k].setPosition(undefined);
                        params.display = false;
                    } else {
                        overlays[k].setPosition(pt); //显示其他站点的label
                        params.display = true;
                    }
                }
                ep.setAttribute("desc", JSON.stringify(params));
            }
            //打开九宫格切换按钮
            funcJggChang('jggShow');
            /////////////////////////////////////////////////////////////////
        }
        //实例化Marker并添加到地图容器中

        var newMarker = new Overlay({
            id: prefix + id,
            name: label,
            position: cpoint,
            positioning: 'center-center',
            element: elementDiv,
            stopEvent: false //为了不遮盖popup，该处stopEvent必须设置为false
        });
        this.map.addOverlay(newMarker);
    }

    addMarkerLabel(pos, flag, id, label, labelParams = {}, labelStyle = { color: '#000' }) {
        var cpoint = fromLonLat(pos);//将地理坐标转为投影坐标
        cpoint = flag == 1 ? cpoint : undefined;
        var map = this.map;
        //新增a元素
        var elementA = document.createElement("div"); //Label
        elementA.className = "ol-mlabel-text";
        //elementA.style.setProperty('font-size', labelStyle.fontSize);
        elementA.style.setProperty('color', labelStyle.color);
        elementA.style.setProperty('text-shadow', '-1px -1px 0 #FFF, 1px -1px 0 #FFF, -1px 1px 0 #FFF, 1px 1px 0 #FFF');//字体描边
        elementA.innerHTML = label; //设置文本
        let prefix = 'label_';
        labelParams.prefix = prefix;
        elementA.setAttribute('desc', JSON.stringify(labelParams));
        var newText = new Overlay({
            id: prefix + id,
            name: label,
            position: cpoint,
            element: elementA,
            stopEvent: false, //为了不遮盖popup，该处stopEvent必须设置为false
            className: 'ol-mlabel-text-container'
        });
        this.map.addOverlay(newText);
    }

    addTag([lon, lat], id, tag, labelParams = {}, labelStyle = { color: '#000', fontSize: '12px' }) {
        var cpoint = fromLonLat([lon, lat]);//将地理坐标转为投影坐标
        var map = this.map;
        //新增a元素
        var elementA = document.createElement("div"); //Label
        elementA.className = "ol-label-text";
        elementA.style.setProperty('font-size', labelStyle.fontSize);
        elementA.style.setProperty('color', labelStyle.color);
        elementA.style.setProperty('text-shadow', '-1px -1px 0 #FFF, 1px -1px 0 #FFF, -1px 1px 0 #FFF, 1px 1px 0 #FFF'); //字体描边
        elementA.innerHTML = tag; //设置文本
        let prefix = 'tag_';
        labelParams.prefix = prefix;
        elementA.setAttribute('desc', JSON.stringify(labelParams));
        var newText = new Overlay({
            id: prefix + id,
            name: tag,
            position: cpoint,
            element: elementA,
            stopEvent: false, //为了不遮盖popup，该处stopEvent必须设置为false
            className: 'ol-label-text-container'
        });
        this.map.addOverlay(newText);
    }

    /*
    addTag([lon, lat], label, minZoom = 6, maxZoom = 10, initZoom = 5) {
        //E.g.: [lon,lat]=[121,32], labelName="Nantong"
        //实例化Vector要素，通过矢量图层添加到地图容器中
        var labelPoint = fromLonLat([lon, lat]); //将地理坐标转为投影坐标
        var labelFeature = new Feature({
            geometry: new Point(labelPoint),
            id: "label_" + label,
            name: label,
        });
        //矢量标注的数据源
        var vectorSource = new SourceVector({
            features: [labelFeature]
        });
        //矢量标注图层
        var vectorLayer = new LayerVector({
            source: vectorSource
        });
        this.map.addLayer(vectorLayer);

        //设置样式
        var _style = new Style({
            text: new Text({
                //位置
                textAlign: 'center',
                //基准线
                textBaseline: 'middle',
                //文字样式
                font: 'normal 0px 微软雅黑',
                //文本内容
                text: labelFeature.get('name'),
                //文本填充样式（即文字颜色）
                fill: new Fill({ color: '#000000' }),
                stroke: new Stroke({ color: '#FFF', width: 1 }),
            }),
            zIndex: 1000,
        });
        labelFeature.setStyle(_style);
        //添加滚轮事件
        var view = this.map.getView();
        view.on('change:resolution', function (feature) {
            // 重新设置标注的尺寸
            var z = viewObj.getZoom();
            if (z >= minZoom && z <= maxZoom) {
                _style.getText().setFont('normal ' + labelZoomSize(initZoom, this.getZoom()) + 'px 微软雅黑');
            } else {
                _style.getText().setFont('normal 0px 微软雅黑');
            }
            labelFeature.setStyle(_style);
        });
        //console.log(labelFeature.getStyle());
    }
    */

    updatePopupInfo(id, info) {
        var overlays = this.map.getOverlays().getArray();
        for (var k in overlays) {
            let oid = overlays[k].getId();
            // 记录位于当前视图的popup
            if (oid == "popup_" + id) {
                let container = overlays[k].get('element'); //获取container
                let content = container.getElementById('content_' + id);
                content.innerHTML = info;
                break;
            }
        }
    }

    getDisplayedPopupsId(map) {//获取当前处于弹窗显示状态的ID编号
        let overlays = map.getOverlays().getArray();
        let ids = [];
        for (var k in overlays) {
            let oid = overlays[k].getId();
            if (oid.indexOf("popup_") >= 0) {//过滤弹窗
                let ep = overlays[k].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let id=params.id;
                if (params.display) {
                    ids.push(id);
                }
            }
        }
        return ids;
    }

    addPopup(pos, flag, id, info, funcLeftClick, funcRightClick, funcJggChang, popupParams = {}) {
        let pt = fromLonLat(pos);//将地理坐标转为投影坐标
        //console.log("addPopup: "+info);
        //创建Popup容器
        var mapDiv = document.getElementById(this.mapId);
        var container = document.createElement('div'); //popup
        var content = document.createElement('div'); //popup-content
        var closer = document.createElement('a'); //popup-closer

        container.setAttribute('class', 'ol-popup');
        container.setAttribute('id', 'container_' + id);
        container.setAttribute('desc', JSON.stringify(popupParams));

        content.setAttribute('class', 'popup-content');
        content.setAttribute('id', 'content_' + id);
        content.innerHTML = info;

        closer.setAttribute('class', 'ol-popup-closer');
        closer.setAttribute('href', '#');
        closer.setAttribute('id', 'close_' + id);
        closer.setAttribute('title', '关闭弹窗');
        closer.innerHTML = '[x]';

        container.appendChild(closer);
        container.appendChild(content);
        //container.appendChild(hidden);
        //mapDiv.appendChild(container);

        //在地图中创建一个Overlay
        var cpoint = flag == 1 ? pt : undefined;
        var popup = new Overlay({
            position: cpoint,
            id: 'popup_' + id,
            //要转换成overlay的HTML元素
            element: container,
            //当前窗口可见
            autoPan: false,
            //Popup放置的位置
            //positioning: 'bottom-center',
            //是否应该停止事件传播到地图窗口
            stopEvent: true, //在popup容器内部点击不触发地图事件，此处必需设置为true
            autoPanAnimation: {
                //当Popup超出地图边界时，为了Popup全部可见，地图移动的速度
                duration: 500
            },
            className: 'ol-popup-container' //控制popup的图层堆叠索引z-index
        });

        container.addEventListener("click", function (evt) {
            //console.log("容器事件源："+evt.target.id+", 类型："+evt.type);
            evt.stopPropagation();   //阻止向父元素冒泡
            evt.preventDefault();    //阻止元素默认行为
            //alert("你点了左键");
            funcLeftClick(id);       //左击事件回调函数
        });

        container.addEventListener("mousedown", function (evt) {
            //console.log("容器事件源："+evt.target.id+", 类型："+evt.type);
            evt.stopPropagation();   //阻止向父元素冒泡
            evt.preventDefault();    //阻止元素默认行为
            if (evt.button == 2) {
                //alert("你点了右键");
                funcRightClick(evt, id);  //右击事件回调函数
            }
        });
        var map = this.map;
        var geoToMrc = this.geoToMrc;
        var getDisplayedPopupsId = this.getDisplayedPopupsId;
        closer.addEventListener("click", function (evt) { //添加关闭按钮的单击事件（隐藏popup）
            //console.log("关闭按钮事件源："+evt.target.id+", 类型："+evt.type);
            evt.stopPropagation();   //阻止向父元素冒泡
            evt.preventDefault();    //阻止元素默认行为
            //未定义popup位置

            popup.setPosition(undefined);
            //失去焦点
            closer.blur();
            let params = JSON.parse(container.getAttribute('desc'));
            params.display = false;
            //alert("当前位置："+params.pos+", 原先位置："+pos);
            container.setAttribute('desc', JSON.stringify(params));
            //return false;
            /////////////////////////////////////////////////////////////////
            //打开当前的MarkerTag和MarkerLabel
            var overlays = map.getOverlays().getArray();
            for (var k in overlays) {
                let oid = overlays[k].getId();
                if (oid == ("label_" + id)) {
                    let ep = overlays[k].get('element');
                    let params = JSON.parse(ep.getAttribute("desc"));
                    let pos = geoToMrc(params.pos);
                    let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
                    //console.log('pos'+"_"+pt);
                    overlays[k].setPosition(pt);  //设置为当前站点位置

                    params.display = true;
                    ep.setAttribute("desc", JSON.stringify(params));
                    break;
                }
            }
            let ids = getDisplayedPopupsId(map);
            if (ids.length == 0) { //当显示的弹窗为0时，关闭九宫格切换按钮
                funcJggChang('jggHidden'); //关闭九宫格切换按钮
            }
            /////////////////////////////////////////////////////////////////
        });
        this.map.addOverlay(popup);
    }

    showAllMarkerLabels(flag = 1) { //显示所有MarkerPin
        var overlays = this.map.getOverlays().getArray(); //获取Overlay要素
        for (var k in overlays) {
            let oid = overlays[k].getId();
            // 记录位于当前视图的popup
            if (oid.indexOf("label_") >= 0) {
                let ep = overlays[k].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let pos = this.geoToMrc(params.pos);
                let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
                //console.log('pos'+"_"+pt);
                if (flag) {
                    overlays[k].setPosition(pt);  //设置为当前站点位置
                    params.display = true;
                } else {
                    overlays[k].setPosition(undefined);  //设置为当前站点位置
                    params.display = false;
                }
                ep.setAttribute("desc", JSON.stringify(params));
            }
        }
    }

    showAllPopups(flag = 1) { //显示所有弹窗
        var overlays = this.map.getOverlays().getArray(); //获取Overlay要素
        var yichang_ids = [];
        var markerHide_ids = [];
        var markerHide_ids_normal = [];
        for (var m in overlays) { //查询处于隐藏状态的站点编号
            let oid = overlays[m].getId();
            let pos = overlays[m].getPosition();
            if (oid.indexOf("marker_") >= 0) {
                let ep = overlays[m].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let id = params.id;
                let zt = params.status;
                if (typeof (pos) == 'undefined') { //如果当前marker处于隐藏状态，比如关闭固定站或便携站
                    markerHide_ids.push(id);
                    if (zt == "正常") {
                        markerHide_ids_normal.push(id);
                    }
                }
            }
        }
        for (var k in overlays) { //显示【设备正常站点】弹窗
            let oid = overlays[k].getId();
            // 记录位于当前视图的popup
            if (oid.indexOf("popup_") >= 0) {
                let ep = overlays[k].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let id = params.id;
                let zt = params.status;
                let pos = this.geoToMrc(params.pos);
                let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
                //console.log('pos'+"_"+pt);
                if (flag && zt == "正常" && !markerHide_ids.includes(id)) {//当前站点的marker没有预先隐藏的话
                    overlays[k].setPosition(pt);  //设置为当前站点位置
                    params.display = true;
                } else {
                    overlays[k].setPosition(undefined);  //设置为当前站点位置
                    params.display = false;
                    if (zt != "正常") {
                        yichang_ids.push(id);
                    }
                }
                ep.setAttribute('desc', JSON.stringify(params)); //更新参数
            }
        }
        //显示【非正常站点】的label
        for (var i in overlays) {
            let oid = overlays[i].getId();
            if (oid.indexOf("label_") >= 0) {
                let ep = overlays[i].get('element');
                let params = JSON.parse(ep.getAttribute("desc"));
                let id = params.id;
                let pos = this.geoToMrc(params.pos);
                let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
                if (!flag && !markerHide_ids.includes(id)) {//如果不显示弹窗，打开所有label
                    overlays[i].setPosition(pt);
                    params.display = true;
                } else {//如果显示弹窗，打开异常站点label
                    if (yichang_ids.includes(id) && !markerHide_ids.includes(id)) { //显示非正常站点的label
                        overlays[i].setPosition(pt);
                        params.display = true;
                    } else {
                        overlays[i].setPosition(undefined);
                        params.display = false;
                    }
                }
                ep.setAttribute("desc", JSON.stringify(params));
            }
        }
        return markerHide_ids_normal;
    }

    showPopupsById(ids) { //显示指定id的站点弹窗
        var overlays = this.map.getOverlays().getArray(); //获取Overlay要素
        for (var k in overlays) { //查询处于隐藏状态的站点编号
            let oid = overlays[k].getId();
            //let pos = overlays[k].getPosition();
            let ep = overlays[k].get('element');
            let params = JSON.parse(ep.getAttribute("desc"));
            let zt = params.status;
            let pos = this.geoToMrc(params.pos);
            let pt = [parseFloat(pos[0]), parseFloat(pos[1])];
            for (var id in ids) {
                if (oid == ("popup_" + ids[id])) {
                    if (zt == "正常") {
                        overlays[k].setPosition(pt);  //设置为当前站点位置
                        params.display = true;
                    } else {
                        overlays[k].setPosition(undefined);  //设置为当前站点位置
                        params.display = false;
                    }
                    ep.setAttribute('desc', JSON.stringify(params)); //更新参数
                    break;
                }
                if (oid == ("label_" + ids[id])) {
                    if (zt == "正常") {
                        overlays[k].setPosition(undefined);
                        params.display = false;
                    } else {
                        overlays[k].setPosition(pt);  //设置为当前站点位置
                        params.display = true;
                    }
                    ep.setAttribute("desc", JSON.stringify(params));
                    break;
                }
            }
        }
    }

}
