<template>
    <div class="arcgis" :class="{'pointer': pointer}">
        <div id="viewDiv"></div>
        <teleport to=".esri-ui" v-if="teleport">
            <div id="marker">
                <div v-for="(marker, index) of markers" :key="index" v-show="marker.show" 
                    :id="'arcgic-marker-' + marker.slot" class="arcgis-marker" :style="'left: '+marker.x+'px; top: '+marker.y+'px; transform: scale('+marker.scale+')'">
                    <slot :name="marker.slot"></slot>
                </div>
            </div>
        </teleport>
    </div>
</template>

<script>
    import Map from "@arcgis/core/Map";
    import Basemap from "@arcgis/core/Basemap";
    import Graphic from "@arcgis/core/Graphic";
    import SpatialReference from "@arcgis/core/geometry/SpatialReference";
    import MapView from "@arcgis/core/views/MapView";
    import SceneView from "@arcgis/core/views/SceneView";
    import MapImageLayer from "@arcgis/core/layers/MapImageLayer";
    import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
    import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol";
    import "@arcgis/core/assets/esri/themes/light/main.css";

    const mapUrl = "http://10.155.32.4:9080/arcgis/rest/services/nxmap/MapServer"; // ArcMap地址
    // const mapUrl = "http://10.155.32.4:9080/arcgis/rest/services/NX_MAP_15/MapServer"; // ArcMap地址
    let basemap = null;
    let map = null;
    let view = null;
    let point_graphicsLayer = null;
    let line_graphicsLayer = null;
    let text_graphicsLayer = null;
    let img_graphicsLayer = null;
    let html_graphicsLayer = null;
    let point_graphics = [];
    let line_graphics = [];
    let text_graphics = [];
    let img_graphics = [];
    let html_graphics = [];

    export default {
        // 名称
        name: "arcgis",
        // 使用组件
        components: {},
        // 传入参数
        props: {
            data: {
                type: Object,
                default: () => {
                    return {
                        mode: "2D", // 模式 2D 3D
                        title: "宁夏地图", // 标题
                        center: [106.230909, 38.487193], // 初始中心点
                        height: 654, // 3D地图初始相机高度
                        tilt: 65, // 俯视角
                        scale: 128000, // 缩放
                        rotation: 0, // 正北顺时针旋转角度
                        ox: 0, // 标记整体偏移
                        oy: 0, // 标记整体偏移
                    }
                },
            }
        },
        // 自定义事件
        emits: {
            when: null, // 地图加载完成
            clickMap: null, // 点击地图(可点击元素)
        },
        // 数据
        data() {
            return {
                fanStateImgMapping: [{
                        name: "待机",
                        code: "0",
                        img: require("@assets/map/fan/green.png")
                    },
                    {
                        name: "运行",
                        code: "1",
                        img: require("@assets/map/fan/blue.png")
                    },
                    {
                        name: "故障",
                        code: "2",
                        img: require("@assets/map/fan/red.png")
                    },
                    {
                        name: "离线",
                        code: "3",
                        img: require("@assets/map/fan/black.png")
                    },               
                    {
                        name: "检修",
                        code: "4",
                        img: require("@assets/map/fan/orange.png")
                    },
                    {
                        name: "限电",
                        code: "5",
                        img: require("@assets/map/fan/purple.png")
                    },
                    {
                        name: "限停",
                        code: "6",
                        img: require("@assets/map/fan/white.png")
                    },
                ],
                syzImg: require("@assets/png/booster-station.png"),
                markers: [],
                pointer: false,
                teleport: false, // 是否进行传送
            }
        },
        // 函数
        methods: {
            // 世界转屏幕
            worldToScreen: function (point) {
                // var world = new Point(point.x, point.y, SpatialReference.WGS84);
                // var screenPoint = map.toScreen(point);
            },
            // 屏幕转世界
            screenToWorld: function (point) {},
            // 偏移转经纬度
            oToLL: function (x, y) {
                return {
                    x: 0.00000899 * x,
                    y: 0.00001141 * y
                }
            },
            // 初始化地图
            initMap: function() {
                basemap = new Basemap({
                    // 底图
                    baseLayers: [
                        new MapImageLayer({
                            url: mapUrl,
                            title: this.data.title,
                            spatialReference: SpatialReference.WGS84,
                        }),
                    ],
                    title: this.data.title,
                    spatialReference: SpatialReference.WGS84,
                });
                map = new Map({
                    // 地图容器
                    basemap: basemap,
                });
                if (this.data.mode == "3D") {
                    view = new SceneView({
                        // 3D显示图层
                        map: map,
                        center: this.data.center,
                        camera: {
                            position: {
                                x: this.data.center[0], // lon
                                y: this.data.center[1], // lat
                                z: this.data.height, // elevation in meters
                            },
                            tilt: this.data.tilt,
                        },
                        container: this.$el.querySelector("#viewDiv"),
                    });
                } else {
                    view = new MapView({
                        // 2D显示图层
                        map: map,
                        center: this.data.center,
                        container: this.$el.querySelector("#viewDiv"),
                        rotation: this.data.rotation,
                    });
                }
                view.scale = this.data.scale;
                //去掉版权
                view.ui._removeComponents(["attribution"]);
                view.when(() => {
                    this.when();
                    this.$emit('when');
                });
            },
            when: function() {
                // 当地图加载完成
                this.teleport = true; // 传送
                point_graphicsLayer = new GraphicsLayer({
                    graphics: []
                });
                line_graphicsLayer = new GraphicsLayer({
                    graphics: []
                });
                text_graphicsLayer = new GraphicsLayer({
                    graphics: []
                });
                img_graphicsLayer = new GraphicsLayer({
                    graphics: []
                });
                html_graphicsLayer = new GraphicsLayer({
                    graphics: []
                });
                map.add(line_graphicsLayer);
                map.add(point_graphicsLayer);
                map.add(text_graphicsLayer);
                map.add(img_graphicsLayer);
                map.add(html_graphicsLayer);
                view.on("click", (event) => { // 监听鼠标点击 判断是否可以点击
                    view.hitTest(event).then((response) => {
                        let result = null;
                        if (response.results.length) {
                            const canClick = ["picture-marker", "text"];
                            response.results.forEach(item => {
                                if (canClick.indexOf(item.graphic.symbol.type) >= 0) {
                                    result = item.graphic.attributes;
                                }
                            })
                        }
                        if (result != null) {
                            this.$emit('clickMap', result);
                        }
                    })
                });
                view.on("pointer-move", (event) => { // 监听鼠标移动 判断是否把鼠标变成小手
                    view.hitTest(event).then((response) => {
                        let result = null;
                        if (response.results.length) {
                            const canClick = ["picture-marker", "text"];
                            response.results.forEach(item => {
                                if (canClick.indexOf(item.graphic.symbol.type) >= 0) {
                                    result = item.graphic.attributes;
                                }
                            })
                        }
                        if (result) {
                            this.pointer= true;
                        } else {
                            this.pointer= false;
                        }
                    })
                })
                view.watch("extent", (evt) => {
                    this.markers.forEach((marker, index) => {
                        let graphics = html_graphics[index];
                        let screenPoint = view.toScreen(graphics.geometry);
                        marker.x = screenPoint.x - marker.ox;
                        marker.y = screenPoint.y - marker.oy;
                        if (marker.canScale) {
                            marker.scale =  0.0272 / evt.height;
                            // console.log(evt.height)
                            if (evt.height < 0.295) { 
                                if (!marker.show) {
                                    marker.show = true;
                                    graphics.symbol = new SimpleMarkerSymbol({
                                        color: "transparent",
                                        outline: {
                                            color: [255, 255, 255],
                                            width: 0
                                        }
                                    });
                                }
                            } else {
                                if (marker.show) {
                                    marker.show = false;
                                    graphics.symbol = new SimpleMarkerSymbol({
                                        color: [5,187,76,0.75],
                                        outline: {
                                            color: [5,187,76],
                                            width: 2
                                        }
                                    });
                                }
                            }
                        }
                    });
                });
            },
            // 通过name或code获取img
            getFanImg: function(nameOrState) {
                const item = this.fanStateImgMapping.find(t => t.name == nameOrState || t.code ==
                    nameOrState);
                if (item) {
                    return item.img;
                } else {
                    console.error(nameOrState, "对应的图片不存在");
                    return "";
                }
            },
            // 添加html
            addHtmlPoint: function (point, slot, ox=0, oy=0, scale=true) {
                point[0] += this.oToLL(this.data.ox, this.data.oy).x;
                point[1] += this.oToLL(this.data.ox, this.data.oy).y;
                let item = {
                    geometry: {
                        type: "point",
                        spatialReference: SpatialReference.WGS84,
                        x: point[0],
                        y: point[1],
                    },
                    symbol: {
                        type: "simple-marker",
                        color: "transparent",
                        outline: {
                            color: [255, 255, 255],
                            width: 0
                        }
                    },
                    // symbol: null,
                    attributes: {},
                    popupTemplate: null
                };
                let graphic = new Graphic(item);
                html_graphics.push(graphic);
                html_graphicsLayer.add(graphic);
                let screenPoint = view.toScreen(graphic.geometry);
                let marker = {
                    slot: slot,
                    ox: ox,
                    oy: oy,
                    x: screenPoint.x - ox,
                    y: screenPoint.y - oy,
                    scale: 1,
                    canScale: scale,
                    show: true,
                };
                this.markers.push(marker);
                return marker;
            },
            // 添加图片点
            addImagePoint: function (point, src, width, height) {
                let item = {
                    geometry: {
                        type: "point",
                        spatialReference: SpatialReference.WGS84,
                        x: point[0],
                        y: point[1]
                    },
                    symbol: {
                        type: "picture-marker",
                        url: this.tempImg,
                        width: width,
                        height: height,
                        xoffset: 0,
                        yoffset: 0
                    },
                    attributes: {},
                    popupTemplate: null
                };
                console.log(item)
                let graphic = new Graphic(item);
                img_graphics.push(graphic);
                img_graphicsLayer.add(graphic);
            },
            // 移除
            remove: function (type, obj) {
                if (type == "html") {
                    let markerIndex = this.markers.findIndex(t => t.slot == obj.slot);
                    // let marker = this.markers[markerIndex];
                    this.markers.splice(markerIndex, 1);
                    let graphic = html_graphics[markerIndex];
                    html_graphics.splice(markerIndex, 1);
                    html_graphicsLayer.remove(graphic);
                } else {
                    console.info("arcgis: No type:", type)
                }
            },
            // 添加图片点
            addImgPoint: function(jsonItem) {
                let item = JSON.parse(JSON.stringify(jsonItem));
                item.geometry.type = "point";
                item.geometry.spatialReference = SpatialReference.WGS84;
                item.geometry.x += this.oToLL(this.data.ox, this.data.oy).x;
                item.geometry.y += this.oToLL(this.data.ox, this.data.oy).y;
                item.symbol = {
                    type: "picture-marker",
                    url: item.attributes.type == "升压站" ? this.syzImg : this.getFanImg(item.attributes.state),
                    width: item.attributes.type == "升压站" ? "96px" : "48px",
                    height: item.attributes.type == "升压站" ? "96px" : "48px",
                    xoffset: 0,
                    yoffset: 18
                };
                let graphic = new Graphic(item);
                point_graphics.push(graphic);
                point_graphicsLayer.add(graphic);
                this.addImgText(jsonItem);
            },
            // 添加图片文字
            addImgText: function(jsonItem) {
                let item = JSON.parse(JSON.stringify(jsonItem));
                item.geometry.type = "point";
                item.geometry.spatialReference = SpatialReference.WGS84;
                item.geometry.x += this.oToLL(this.data.ox, this.data.oy).x;
                item.geometry.y += this.oToLL(this.data.ox, this.data.oy).y;
                item.symbol = {
                    type: "text",
                    color: "white",
                    haloColor: "black",
                    haloSize: "1px",
                    text: item.attributes.code,
                    xoffset: 0,
                    yoffset: -10,
                    font: {
                        size: 12,
                        // family: "Josefin Slab",/
                        weight: "bold"
                    }
                };
                let graphic = new Graphic(item);
                text_graphics.push(graphic);
                text_graphicsLayer.add(graphic);
            },
            // 添加线段
            addLine: function(jsonItem) {
                let item = JSON.parse(JSON.stringify(jsonItem));
                item.geometry.type = "polyline";
                item.geometry.spatialReference = SpatialReference.WGS84;
                item.geometry.paths.forEach(item => {
                    item[0] += this.oToLL(this.data.ox, this.data.oy).x;
                    item[1] += this.oToLL(this.data.ox, this.data.oy).y;
                });
                item.symbol = {
                    type: "simple-line",
                    color: "#05bb4c",
                    width: item.attributes.width,
                }
                let graphic = new Graphic(item);
                line_graphics.push(graphic);
                line_graphicsLayer.add(graphic);
            },
            addFanByJson: function(jsonObj, lineJsonObj) {
                // jsonObj.forEach(item => {
                //     this.addImgPoint(item);
                // });
                lineJsonObj.forEach(item => {
                    this.addLine(item);
                });
            },
            goto: function(point) {
                view.goTo({
                    center: point
                }).catch(function(error) {
                    if (error.name != "AbortError") {
                        console.error(error);
                    }
                });
            }
        },
        // 生命周期钩子
        beforeCreate() {
            // 创建前
        },
        created() {
            // 创建后
        },
        beforeMount() {
            // 渲染前
        },
        mounted() {
            // 渲染后
			basemap = null;
            map = null;
            view = null;
            point_graphicsLayer = null;
            line_graphicsLayer = null;
            text_graphicsLayer = null;
            img_graphicsLayer = null;
            html_graphicsLayer = null;
            point_graphics = [];
            line_graphics = [];
            text_graphics = [];
            img_graphics = [];
            html_graphics = [];
            this.initMap();
        },
        beforeUpdate() {
            // 数据更新前
        },
        updated() {
            // 数据更新后
        },
    }
</script>

<style lang="less">
    .arcgis {
        width: 100%;
        height: 100%;
        position: relative;
        overflow: hidden;

        &.pointer {
            cursor: pointer;
        }

        #viewDiv {
            position: absolute;
            z-index: 1;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
        }

        #marker {
            position: absolute;
            z-index: 2;
            width: 0;
            height: 0;
            top: 0;
            left: 0;
        }

        .arcgis-marker {
            position: absolute;
            z-index: 2;
        }
    }
</style>
