<template>
    <div>
        <slot>
        </slot>
    </div>
</template>

<script>
    import * as Util from './Util'
    import { HttpResetClass } from 'vue-client'
    import Vue from 'vue'
    import Proj4 from 'proj4'
    import 'ol/ol.css'
    import Map from 'ol/map'
    import View from 'ol/view'
    import XYZ from 'ol/source/xyz'
    import Zoom from 'ol/control/zoom'
    import Tile from 'ol/layer/tile'
    import OSM from 'ol/source/osm'
    import ScaleLine from 'ol/control/scaleline'
    import Proj from 'ol/proj'
    import TileJSON from 'ol/source/tilejson'
    import TileArcGISRest from 'ol/source/tilearcgisrest'
    import TileGrid from 'ol/tilegrid/tilegrid'
    import MousePosition from 'ol/control/mouseposition'
    import Coordinate from 'ol/coordinate'
    import Feature from 'ol/feature'
    import Point from 'ol/geom/point'
    import Style from 'ol/style/style'
    import Text from 'ol/style/text'
    import Circle from 'ol/style/circle'
    import Fill from 'ol/style/fill'
    import Stroke from 'ol/style/stroke'
    import VectorSource from 'ol/source/vector'
    import Vector from 'ol/layer/vector'
    import DragBox from './dragbox'
    import Condition from 'ol/events/condition'
    import Control from 'ol/control/control'
    import Ol from 'ol'
    import LineString from 'ol/geom/linestring'

    const Projs = {
        'EPSG:2381': '+proj=tmerc +lat_0=0 +lon_0=108 +k=1 +x_0=500000 +y_0=0 +a=6378140 +b=6356755.288157528 +units=m +no_defs',
    }

    const ToggleControl = function(opt_options) {

        var options = opt_options || {}

        var button = document.createElement('button')
        button.innerHTML = '移'

        var this_ = this
        var toggleSelect = function() {
            let gadget = this_.map_.vuecomponent
            if (button.innerHTML === '选') {
                gadget.olmap.removeInteraction(gadget.dragbox)
                button.innerHTML = '移'
            } else {
                gadget.olmap.addInteraction(gadget.dragbox)
                button.innerHTML = '选'
            }
        };

        button.addEventListener('click', toggleSelect, false)

        var element = document.createElement('div')
        element.className = 'toggle-drag ol-unselectable ol-control'
        element.appendChild(button)

        Control.call(this, {
            element: element,
            target: options.target
        })

    }

    Ol.inherits(ToggleControl, Control)

    const CurGeoControl = function(opt_options) {

        var options = opt_options || {}

        var button = document.createElement('button')
        button.innerHTML = '我'

        var this_ = this
        var locSelect = function() {
            let gadget = this_.map_.vuecomponent
            gadget.setH5Geo()
        };

        button.addEventListener('click', locSelect, false)

        var element = document.createElement('div')
        element.className = 'cur-geo ol-unselectable ol-control'
        element.appendChild(button)

        Control.call(this, {
            element: element,
            target: options.target
        })

    }

    Ol.inherits(CurGeoControl, Control)

    const ActiveRepairmanControl = function(opt_options) {

        var options = opt_options || {}

        var button = document.createElement('button')
        button.innerHTML = '维'

        var this_ = this
        var locSelect = function() {
            let gadget = this_.map_.vuecomponent
            gadget.hilitActiveRepairman()
        };

        button.addEventListener('click', locSelect, false)

        var element = document.createElement('div')
        element.className = 'active-repairman ol-unselectable ol-control'
        element.appendChild(button)

        Control.call(this, {
            element: element,
            target: options.target
        })

    }

    Ol.inherits(ActiveRepairmanControl, Control)

    const ActiveUserControl = function(opt_options) {

        var options = opt_options || {}

        var button = document.createElement('button')
        button.innerHTML = '用'

        var this_ = this
        var locSelect = function() {
            let gadget = this_.map_.vuecomponent
            gadget.hilitActiveUser()
        };

        button.addEventListener('click', locSelect, false)

        var element = document.createElement('div')
        element.className = 'active-user ol-unselectable ol-control'
        element.appendChild(button)

        Control.call(this, {
            element: element,
            target: options.target
        })

    }

    Ol.inherits(ActiveUserControl, Control)

    export default {
        title: 'CallCtxMap',
        name: 'CallCtxMap',
        props: {
            map: {
                type: Object,
                default: _ => {
                    return {
                        center: [3206.764198839668,3155.45597165823],
                        curz: 2,
                        minz: 2,
                        maxz: 9,
                        mapp: 'EPSG:2381',
                        viewp: 'EPSG:2381',
                        ext: [-8254.48211669922, -9234.77789306641, 18015.3302001953, 13400.870605468801],
                    }
                }
            },
            layers: {
                type: Array,
                default: _ => [
                    // {
                    //     lt: 'xyz',
                    //     url: 'http://192.168.2.54:6080/arcgis/rest/services/基础地形图/MapServer/tile/{z}/{y}/{x}',
                    //     ext: [-8254.48211669922, -9234.77789306641, 18015.3302001953, 13400.870605468801],
                    //     ori: [-5123200.0, 1.00021E7],
                    //     res: [
                    //         31.750063500127002,
                    //         15.875031750063501,
                    //         7.9375158750317505,
                    //         3.9687579375158752,
                    //         2.116670900008467,
                    //         1.0583354500042335,
                    //         0.5291677250021167,
                    //         0.26458386250105836,
                    //         0.13229193125052918,
                    //         0.05291677250021167,
                    //     ],
                    //     tileSize: 256,
                    // },
                    {
                        lt: 'arcTile',
                        url: 'http://192.168.2.54:6080/arcgis/rest/services/基础地形图/MapServer',
                    },
                    {
                        lt: 'arcTile',
                        url: 'http://192.168.2.54:6080/arcgis/rest/services/管网/MapServer',
                    },
                ]
            },
            dragbox: {
                type: Boolean,
                default: false,
                hint: '是否有拉框选择控件'
            },
            curPipe: {
                type: String,
                default: null,
            },
            showCurGeo: {
                type: Boolean,
                default: false,
                hint: '是否显示当前地理位置'
            },
            showActiveRepairmanPos: {
                type: Boolean,
                default: false,
                hint: '是否显示当前维修员位置'
            },
            showActiveUserPos: {
                type: Boolean,
                default: false,
                hint: '是否显示当前用户立管位置'
            }
        },
        data () {
            return {
                olmap: null,
                repairmanlayer: null,   //所有当前维修员图层
                userlayer: null,        //预留显示用户小区的图层
                pipelayer: null,        //金剑管道图层
                plumblayer: null,       //立管高亮图层
                melayer: null,          //我的当前位置高亮图层
                hiRepairmanLayer: null  //当前维修员高亮图层
            }
        },

        methods: {
            setProj: function (proj, ext) {
                Proj4.defs(proj, Projs[proj])
                Proj.get(proj).setExtent(ext)
            },

            initMap: function () {
                this.$el.style.overflow = 'hidden'
                this.$el.style.height = "100%"

                if(!Proj.get(this.map.mapp)) {
                    this.setProj(this.map.mapp, this.map.ext)
                }
                if(!Proj.get(this.map.viewp)) {
                    this.setProj(this.map.viewp, this.map.ext)
                }
            },

            initLayers: function (strata) {
                this.layers.forEach(ele => {
                    if(ele.lt === 'xyz') {
                        strata.push(
                            new Tile({
                                source: new XYZ({
                                    tileGrid: new TileGrid({
                                        tileSize: ele.tileSize,
                                        origin: ele.ori,
                                        extent: ele.ext,
                                        resolutions: ele.res,
                                    }),
                                    url: ele.url,
                                    projection: this.map.mapp,
                                })
                            })
                        )
                    } else if(ele.lt === 'arcTile') {
                        strata.push(
                            new Tile({
                                source: new TileArcGISRest({
                                    url: ele.url,
                                    projection: this.map.mapp,
                                })
                            })
                        )
                    }
                })
            },

            createMap: function (strata) {
                let controls = [
                    new Zoom({
                        className: 'ol-zoom2'
                    }),
                    new ScaleLine({
                        className: 'ol-scale-line2'
                    }),
                    new MousePosition({
                        coordinateFormat: Coordinate.createStringXY(3),
                        projection: this.map.mapp,
                    }),
                ]

                if(this.dragbox) {
                    controls.push(new ToggleControl({}))
                }

                if(this.showCurGeo) {
                    controls.push(new CurGeoControl({}))
                }

                if(this.showActiveRepairmanPos) {
                    controls.push(new ActiveRepairmanControl({}))
                }

                if(this.showActiveUserPos) {
                    controls.push(new ActiveUserControl({}))
                }

                let olmap = new Map({
                    target: this.$el,
                    loadTilesWhileAnimating: true,
                    controls: controls,
                    layers: strata,
                    view: new View({
                        center: this.map.center,
                        zoom: this.map.curz,
                        minZoom: this.map.minz,
                        maxZoom: this.map.mzxz,
                        projection: this.map.viewp,
                    })
                })
                return olmap
            },

            setCenterXY: function(xy) {
                this.olmap.getView().setCenter(xy)
            },

            setZoom: function(val) {
                this.olmap.getView().setZoom(val)
            },

            plotUser: function (xy, label) {
                let f = new Feature({
                    geometry: new Point(xy)
                })
                let s = new Style({
                    image: new Circle({
                        radius: 8,
                        snapToPixel: false,
                        fill: new Fill({
                            color: 'blue',
                        }),
                        stroke: new Stroke({
                            color: 'blue',
                            width: 1,
                        })
                    }),
                    text: new Text({
                        text: label,
                    }),
                })
                f.setStyle(s)

                f.tag = {
                    type: 'poiArea',
                    data: label
                }

                if(this.userlayer)
                    this.clearOverlays('userlayer')

                this.userlayer = new Vector({
                    source: new VectorSource({
                        features: [f],
                    })
                })

                this.olmap.addLayer(this.userlayer)

                this.setCenterXY(xy)
            },

            plotRepairman: function (lolas, style) {
                let features = []
                let i, len

                if(lolas.length > 0) {

                    let c1 = []
                    let c2 = []
                    let p = lolas[0]
                    //p = Proj.fromLonLat(p, this.map.mapp)
                    //transform(p)
                    c1[0] = p[0]
                    c1[1] = p[1]
                    c2[0] = c1[0]
                    c2[1] = c1[1]

                    for(i=0, len=lolas.length; i<len; i++) {
                        p = [lolas[i][0], lolas[i][1]]
                        //p = Proj.fromLonLat(p, this.map.mapp)
                        //transform(p)
                        if(p[0] < c1[0])
                            c1[0] = p[0]
                        if(p[1] < c1[1])
                            c1[1] = p[1]
                        if(p[0] > c2[0])
                            c2[0] = p[0]
                        if(p[1] > c2[1])
                            c2[1] = p[1]
                        let f = new Feature({
                            geometry: new Point(p)
                        })
                        f.tag = {
                            type: 'poiRepairman',
                            data: lolas[i]
                        }
                        features.push(f)

                        if(!style) {
                            let s = new Style({
                                image: new Circle({
                                    radius: 4,
                                    snapToPixel: false,
                                    fill: new Fill({
                                        color: 'blue',
                                    }),
                                    stroke: new Stroke({
                                        color: 'blue',
                                        width: 1,
                                    })
                                }),
                                text: new Text({
                                    text: lolas[i][2],
                                }),
                            })
                            f.setStyle(s)
                        } else {
                            f.setStyle(style)
                        }
                    }

                    if(this.repairmanlayer)
                        this.clearOverlays('repairmanlayer')

                    this.repairmanlayer = new Vector({
                        source: new VectorSource({
                            features: features,
                        })
                    })

                    this.olmap.addLayer(this.repairmanlayer)
                    // if(lolas.length > 1)
                    //     this.olmap.getView().fit([c1[0], c1[1], c2[0], c2[1]], this.olmap.getSize())
                    // else
                    this.setCenterXY([c1[0], c1[1]])

                }
            },

            plotPipe: function (paths) {
                let f = new Feature({
                    geometry: new LineString(paths)
                })
                let s = new Style({
                    stroke: new Stroke({
                        color: 'yellow',
                        width: 8,
                    }),
                })
                f.setStyle(s)

                f.tag = {
                    type: 'poiPipe',
                    data: paths
                }

                if(this.pipelayer)
                    this.clearOverlays('pipelayer')

                this.pipelayer = new Vector({
                    source: new VectorSource({
                        features: [f],
                    })
                })

                this.olmap.addLayer(this.pipelayer)
                this.setCenterXY([(paths[0][0]+paths[1][0])/2, (paths[0][1]+paths[1][1])/2])
                //this.setZoom(8)

            },

            clearOverlays: function (layer) {
                if(!layer) {
                    if(this.userlayer)
                        this.olmap.removeLayer(this.userlayer)
                    if(this.repairmanlayer)
                        this.olmap.removeLayer(this.repairmanlayer)
                    if(this.pipelayer)
                        this.olmap.removeLayer(this.pipelayer)
                    if(this.plumblayer)
                        this.olmap.removeLayer(this.plumblayer)
                    if(this.melayer)
                        this.olmap.removeLayer(this.melayer)
                    if(this.hiRepairmanLayer)
                        this.olmap.removeLayer(this.hiRepairmanLayer)
                } else {
                    this.olmap.removeLayer(this[layer])
                }
            },

            plotPlumb: function (xy, label) {

                let f = new Feature({
                    geometry: new Point(xy)
                })
                let s = new Style({
                    image: new Circle({
                        radius: 8,
                        snapToPixel: false,
                        fill: new Fill({
                            color: 'yellow',
                        }),
                        stroke: new Stroke({
                            color: 'red',
                            width: 1,
                        })
                    }),
                    text: new Text({
                        text: label,
                    }),
                })
                f.setStyle(s)

                f.tag = {
                    type: 'poiPlumb',
                    data: label
                }

                if(this.plumblayer)
                    this.clearOverlays('plumblayer')
                if (!label)
                    return
                console.log('开始标记')
                this.plumblayer = new Vector({
                    source: new VectorSource({
                        features: [f],
                    })
                })

                this.olmap.addLayer(this.plumblayer)

                this.setCenterXY(xy)

                //this.setZoom(6)

            },

          plotMe: function (xy) {
            let f = new Feature({
              geometry: new Point(xy)
            })
            let s = new Style({
              image: new Circle({
                radius: 8,
                snapToPixel: false,
                fill: new Fill({
                  color: 'blue',
                }),
                stroke: new Stroke({
                  color: 'red',
                  width: 1,
                })
              })
            })
            f.setStyle(s)

            f.tag = {
              type: 'poiMe',
              data: null
            }

            if(this.melayer)
              this.clearOverlays('melayer')

            this.melayer = new Vector({
              source: new VectorSource({
                features: [f],
              })
            })

            this.olmap.addLayer(this.melayer)

            // this.setCenterXY(xy)

            // this.setZoom(6)

          },

            hilightARepairman: function (xy, label) {
                let f = new Feature({
                    geometry: new Point(xy)
                })
                let s = new Style({
                    image: new Circle({
                        radius: 8,
                        snapToPixel: false,
                        fill: new Fill({
                            color: 'blue',
                        }),
                        stroke: new Stroke({
                            color: 'red',
                            width: 1,
                        })
                    }),
                    text: new Text({
                        text: label,
                    }),
                })
                f.setStyle(s)

                f.tag = {
                    type: 'poiHiRepairman',
                    data: label
                }

                if(this.hiRepairmanLayer)
                    this.clearOverlays('hiRepairmanLayer')

                this.hiRepairmanLayer = new Vector({
                    source: new VectorSource({
                        features: [f],
                    })
                })

                this.olmap.addLayer(this.hiRepairmanLayer)

                this.setCenterXY(xy)

                //this.setZoom(6)

            },

            rafshim() {
                var lastTime = 0
                var vendors = ['ms', 'moz', 'webkit', 'o']
                for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
                    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']
                    window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']
                }

                console.log('window.requestAnimationFrame:' + window.requestAnimationFrame)
                if (!window.requestAnimationFrame)
                    window.requestAnimationFrame = function(callback, element) {
                        var currTime = new Date().getTime()
                        var timeToCall = Math.max(0, 16 - (currTime - lastTime))
                        var id = window.setTimeout(function() { callback(currTime + timeToCall) },
                            timeToCall)
                        lastTime = currTime + timeToCall
                        return id
                    }

                if (!window.cancelAnimationFrame)
                    window.cancelAnimationFrame = function(id) {
                        clearTimeout(id)
                    }
                console.log('window.requestAnimationFrame:' + window.requestAnimationFrame)
            },

            setH5Geo: function() {
              // 获取当前位置信息
                let res = HostApp.getNowLocalInfo();
                console.log("立管挂接获取当前位置信息" + JSON.stringify(res))
                if(res.code == 200){
                  let http1 = new HttpResetClass()
                  let dataurl = `${this.$androidUtil.getProxyUrl()}/AZTEST/LPResource/LPService/JJGISCoordinateService.asmx/WGS84ToLocal?wgs84Lng=${res.data.f_longitude}&wgs84Lat=${res.data.f_latitude}`
                  http1.load('Get', dataurl,{}, {warnMsg: null,resolveMsg: null, rejectMsg: '查询失败！'}).then((rat)=>{
                    let strdata =rat.data.toString()
                    strdata =   strdata.replace('<?xml version="1.0" encoding="utf-8"?>','').replace('<string xmlns="http://jjgis.com.cn/">','').replace('</string>','')
                    strdata = strdata.replace(/↵/g,"")
                    let arr= []
                    arr = strdata.split("|")
                    this.plotMe(arr)
                  })
                }else{
                  this.$showMessage('未获取到位置信息')
                }
            },

            hilightChosenPlumb: function() {
                this.$parent.hilightBonded(this.$parent.curPipe)
            },

            hilitActiveRepairman: function () {
                this.$parent.hilitActiveRepairman()
            },

            hilitActiveUser: function () {
                this.$parent.hilitActiveUser()
            }

        },

        ready () {
            console.log('olmap ready')

            this.rafshim()

            Proj.setProj4(Proj4)

            this.initMap()

            let layers = []
            this.initLayers(layers)

            this.olmap = this.createMap(layers)

            //show initial selected plumb
            if(this.$parent.curPipe)
                this.olmap.once('postrender', this.hilightChosenPlumb, this)

            if(this.dragbox) {
                this.dragbox = new DragBox({})
                this.dragbox.on('boxstart', ev => {
                    this.$emit('clear-select')
                })
                this.dragbox.on('boxend', ev => {
                    console.log('done-select:' + this.dragbox.getGeometry().getExtent())
                    this.$emit('done-select', this.dragbox.getGeometry().getExtent())
                })
            }

            if(this.dragbox || this.showCurGeo || this.showActiveRepairmanPos || this.showActiveUserPos) {
                this.olmap.vuecomponent = this
            }

            this.olmap.on('click', ev => {
                const feature = this.olmap.forEachFeatureAtPixel(ev.pixel, feature => feature)
                if(feature) {
                    this.$emit('feature-selected', ev, feature)
                } else {
                    // this.$emit('map-clicked', ev)
                }
            })

        },

        events: {
            // 添加标记
            'addMarker': function(m) {
                console.log('Marker added.')
                this.olmap.addLayer(m)
            },

            // 移除标记
            'removeMarker': function(m) {
                this.olmap.removeLayer(m)
            },

            // 清除所有的覆盖层
            'removeOverlays': function(m) {
                this.clearOverlays()
            },

            // 显示所有的维修员位置
            'poi-repairman' : function (points) {
                this.plotRepairman(points)
            },

            // 未使用
            'poi-pipe' : function (path) {
                this.plotPipe(path)
            },

            // 高亮当前立管
            'poi-plumb' : function (xy, label) {
                console.log('高亮')
                console.log('label')
                this.plotPlumb(xy, label)
            },

            // 未使用, 用来高亮用户小区 misnomer
            'user-changed' : function (xy, label) {
                this.plotUser(xy, label)
            },

            // 高亮当前维修员
            'hilit-a-repairman' : function(xy, repairman) {
                this.hilightARepairman(xy, repairman)
            }
        },


    }
</script>

<style>
    .ol-zoom2 {
        top: .5em;
        left: .5em;
        height: auto;
    }

    .ol-scale-line2 {
        bottom: 8px;
        left: 8px;
        position: absolute;
        background: rgba(0, 60, 136, 0.3);
        border-radius: 4px;
        padding: 2px;
        height: auto;
    }

    .toggle-drag {
        top: 80px;
        left: .5em;
    }

    .cur-geo {
        top: 120px;
        left: .5em;
    }

    .active-repairman{
        top: 80px;
        left: .5em;
    }

    .active-user{
        top: 120px;
        left: .5em;
    }

</style>
