<template>
    <div class="draw-box" v-if="visible" >
        <div class="title">
            <span>{{modelMap[viewModel]}}</span>
            <div class="actions">
                <div class="btn" @click="drawScreenFull">全屏</div>
                <i class="btn el-icon-close" @click="closePop()"></i>
            </div>
        </div>
        <div class="content-box">
            <div class="update-box">
                <div class="form-box">
                    <FormComponent v-if="viewModel!=='list'" labelWidth="56px" :isReadonly="isReadonly" :fullBtn="true" :btnPosition="'center'" @change="change" :data.sync="updateParams" @actionCallback="callback" :options="options" :actions="actions"></FormComponent>
                    <FormComponent v-else labelWidth="56px" @input="change" :data.sync="listParams" :options="listForm" ></FormComponent>
                </div>
                <div class="tree-box" v-if="viewModel==='list'">
                    <el-tree :data="treeData" :props="{children:'children',label:'name'}" :expand-on-click-node="false" default-expand-all highlight-current 
                        :filter-node-method="filterNode"
                        ref="tree" @node-click="handleNodeClick">
                         <span class="custom-tree-node" slot-scope="{ node, data }">
                            <span class="text-block">{{ node.label }}</span>
                            <span>
                                <el-button
                                    v-if="!data.geoJson || data.geoJson==='[]'"
                                    type="text"
                                    size="mini"
                                    @click="() => drawNode(data)">
                                    绘制
                                </el-button>
                                <el-tag v-else  size="mini" type="success">已绘制</el-tag>
                            </span>
                        </span>
                    </el-tree>
                </div>
            </div>
            <div class="map-box" ref="draw">
                <MapComponent @onLoad="getMap"></MapComponent>
            </div>
        </div>
    </div>
</template>
<script lang="ts">
import FormComponent from 'hbt-common/components/common/form.component.vue';
import { Component, Emit, Prop, PropSync, Vue, Watch } from 'vue-property-decorator';
import MapComponent from './map.component.vue';
import screenfull from "screenfull"
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import * as turf from '@turf/turf'
import UnitService from '@/service/unit.service';
import AreaService from '@/service/area.service';
@Component({
    components:{
        MapComponent,
        FormComponent
    }
})
export default class DrawComponent extends Vue {

    public unitService = new UnitService()
    public areaService = new AreaService()

    public treeData = [] as any;

    public modelMap = {
        list:"批量绘制",
        area:"区域绘制",
        unit:"单元绘制"
    }

    public listForm = [{
        name:"关键词",
        key:"keyword",
        width:"100%",
        type:"text",
        placeholder:"请输入名称关键词",
    }];
    public listParams = {
        keyword:""
    }

    public map:any;

    public updateParams = {} as any;

    public positions = [] as any;

    public hasInitDraw = false;
    public options = [];
    public actions = [];
    
    public draw = new MapboxDraw({
        displayControlsDefault: false,
        // Select which mapbox-gl-draw control buttons to add to the map.
        controls: {
            polygon: true,
            trash: true
        },
        // Set mapbox-gl-draw to draw by default.
        // The user does not have to click the polygon control button first.
        defaultMode: 'draw_polygon'
    })
    @PropSync("model")
    public viewModel:string;
    @Prop()
    public isReadonly:boolean;
    @PropSync("show",{
        required:true,
        default:true
    })
    public visible:boolean;
    @PropSync("data",{
        required:true,
    })
    public params!:any;

    public fromList = false;

    @Watch("params",{immediate:true,deep:true})
    onChanges(newVal,odlVal){
        this.updateParams = JSON.parse(JSON.stringify(newVal))
        if(newVal.geoJson){
            this.positions = JSON.parse(newVal.geoJson);

            if(this.positions.length){
                this.flyToCenter(16)
            }
            if(this.map){

                this.addAllPolygon();
            }
        }
    }

    @Watch("viewModel",{immediate:true,deep:true})
    onModelChanges(newVal){
        if(newVal==="list"){
            this.fromList = true;
            this.setTreeData();
        }
       this.buildUpdate()
    }
    @Watch("visible",{immediate:true,deep:true})
    onVisibleChanges(newVal){
        //     console.log("close")
        // if(!newVal){
        // }
    }

    @Emit("onClose")
    onClose(data){
        //Emit false
    }

    created(){
        // this.positions = [] as any;
    }

    public flyToCenter(zoom,timer?){
        if(!this.map ){
            return
        }
        const center = turf.centerOfMass(turf.featureCollection(this.positions));
        this.map.flyTo({center: center.geometry.coordinates, zoom: zoom});
        this.addAllPolygon();
    }

    public setTreeData(){
        this.unitService.getUnitTree().then(res=>{
            this.treeData = res.data;
            this.positions = this.getAllFeatures(this.treeData);
            if(this.positions.length && this.map){
                this.addAllPolygon();
            }
        })
    }

    public getMap(map){
        this.map = map;
        this.map.on('draw.create', this.drawCallback);
        this.map.on('draw.delete', this.drawCallback);
        this.map.on('draw.update', this.drawCallback);
        if(this.positions.length){
            this.addAllPolygon();
                this.flyToCenter(this.fromList?14:16)
        }
    }

    public getAllFeatures(datas,result?){
        if(!result){
            result = []
        }
        datas.forEach((item)=>{
            result.push(...JSON.parse(item.geoJson));
            if(item.children){
                result = this.getAllFeatures(item.children,result)
            }
        });
        return result
    }

    public addAllPolygon(){
        const featureCollection = turf.featureCollection(this.positions);
        if(!this.map.getSource('allDataSource')){
            this.map.addSource("allDataSource", {
                type: "geojson",
                data: featureCollection,
            });
            this.map.addLayer({
                id:"allDataLayer",
                source:"allDataSource",
                type:"fill-extrusion",
                paint:{
                    "fill-extrusion-color":"#38fcf9",
                    "fill-extrusion-base":["get","bottomHeight"],
                    "fill-extrusion-height":["get","topHeight"],
                    "fill-extrusion-opacity":0.6
                }
            });
            this.map.addLayer({
                "id": "textLayer",
                "type": "symbol",
                "source": "allDataSource",
                "layout": {
                    "text-field": ["get", "name"],
                    "text-size": [
                    'interpolate',
                    // Set the exponential rate of change to 0.5
                    ['exponential', 0.5],
                    ['zoom'],
                    // When zoom is 15, buildings will be beige.
                    15,
                    12,
                    // When zoom is 18 or higher, buildings will be yellow.
                    18,
                    24,
                    ],
                    // "text-allow-overlap": true
                },
                "paint": {
                    "text-color": "#FFF",
                    "text-halo-color": "#000",
                    "text-halo-width": 10
                }
            })
        }else{
            this.map.getSource("allDataSource").setData(featureCollection)
        }
        
    }

    public removeLayer(){
        if(!this.map){
            return
        }
        if(this.map.getSource("allDataSource")){
            this.map.removeLayer("allDataLayer")
            this.map.removeLayer("textLayer")
            this.map.removeSource("allDataSource")
        }
    }

    public drawCallback(e){
        if(e.type ==="draw.create"){
            this.positions = this.positions.concat(e.features)
        }else if(e.type ==="draw.update"){
            this.positions.splice(this.positions.findIndex((item:any)=>item.id===e.features[0].id),1,e.features[0])
        }else{
            this.positions.splice(this.positions.findIndex((item:any)=>item.id===e.features[0].id),1)
        }
        // console.log(this.positions)
    }

    public drawScreenFull(){
        screenfull.toggle(this.$refs.draw as any);
        if(this.map){
            this.map.resize()
        }
    }
    // 树节点过滤
    public filterNode(value, data) {
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
    }

    public change(data,meta){
        if(meta.key === "keyword"){
            (this.$refs.tree as any).filter(data)
        }
    }

    public handleNodeClick(node){
        const geoJson = JSON.parse(node.geoJson);
        if(!geoJson.length){
            return
        }
        const center = turf.centerOfMass(turf.featureCollection(geoJson));
        this.map.flyTo({center: center.geometry.coordinates, zoom: 18});
    }

    public drawNode(data){
        this.params =Object.assign({bottomHeight:0,topHeight:0,geoJson:"[]"},data) as any;
        if(data.areaId){
            this.viewModel = "unit"
        }else{
            this.viewModel = "area"
        }

    }
    // 点击绘制
    public drawCallBack(){
        if(!this.map){
            this.$message.error("地图未初始化完成，请稍后再试")
            return
        }
        if(this.hasInitDraw){
            this.$message.error("绘制工具已打开请点击地图右上角进行绘制")
            return
        }
        this.map.addControl(this.draw);
        if(this.positions.length){
            this.removeLayer()
            this.positions.forEach(feature=>{
                this.draw.add(feature)
            })
        }
        this.hasInitDraw = true;
    }

    public destoryDraw(){
        this.map.removeControl(this.draw);
        this.hasInitDraw = false;
    }

    // 点击保存
    public doSave(){
        if(this.updateParams.topHeight<this.updateParams.bottomHeight){
            this.$message.error("顶部高度不能小于底部高度")
            return
        }
        if(!this.positions.length){
            this.$message.error("请绘制地图位置信息");
            return
        }
        this.positions.forEach(feature=>{
            feature.properties = this.updateParams
        })
        this.updateParams.geoJson = JSON.stringify(this.positions);
        if(this.fromList){
            const service = this.viewModel==='unit'?this.unitService:this.areaService;
            service.addOrUpdate(this.updateParams,false).then(res=>{
                this.viewModel = "list";
                this.destoryDraw();
                this.setTreeData()
            })
            this.onClose(false)
        }else{
            this.params = this.updateParams;
            this.visible = false;
        }
    }

    

    public callback(action){
        if(action.value==="draw"){
            this.drawCallBack();
        }else if(action.value==="save"){
            this.doSave()
        }else {
            if(this.fromList){
                this.viewModel = "list";
                if(this.hasInitDraw){
                    this.draw.deleteAll()
                }
            }else{
                this.visible = false;
            }
            this.updateParams = {} as any;
            
        }
    }


    public buildUpdate(){
        this.options = [{
            name:"区域名称",
            width:"100%",
            hide:this.viewModel === "unit",
            key:"name",
            disable:true,
            type:"text",
            placeholder:"请输入区域名称",
        },{
            name:"单元名称",
            key:"name",
            hide:this.viewModel === "area",
            width:"100%",
            disable:true,
            type:"text",
            placeholder:"请输入单元名称",
        },{
            name:"顶部高度",
            key:"topHeight",
            width:"100%",
            type:"number",
            placeholder:"",
        },{
            name:"底部高度",
            key:"bottomHeight",
            width:"100%",
            type:"number",
            placeholder:"",
        }] as any;

        this.actions = [{
            name:"绘制",
            value:"draw",
            icon:"el-icon-edit",
            type:"primary"
        },{
            name:"保存",
            value:"save",
            icon:"el-icon-s-order",
            type:"primary"
        },{
            name:"取消",
            icon:"el-icon-tickets",
            value:"cancel"
        }] as any;
    }

    mounted(){
    }


    public closePop(){
        this.removeMap();
        this.updateParams = {} as any;
        this.onClose(false)
        this.visible = false;
    }

    public removeMap(){
        this.map.off('draw.create', this.drawCallback);
        this.map.off('draw.delete', this.drawCallback);
        this.map.off('draw.update', this.drawCallback);
        this.removeLayer();
        this.map.remove();
        this.map = null;
    }
    // destroyed(){
    //     // console.log(123)
    //     this.removeMap()
    // }
}
</script>
<style lang="scss" scoped>
::v-deep{
.el-button{
    padding: 0 8px;
    height: 40px;
    line-height: 40px;
}
.el-tree-node__content{
    height: auto;
}
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content .el-button--text{
    color: #FFF;
}

}
.draw-box{
    width: 100%;
    height: 100%;
    border-radius: 8px;
    background: #FFF;
    padding: 0 40px 40px;
    display: flex;
    flex-direction: column;
    position: relative;
    z-index: 1000;
    .title{
        height: 68px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid #EEE;
        font-size: 20px;
        color: #606266;
        .actions{
            display: inline-flex;
            align-items: center;
            .btn{
                cursor: pointer;
                font-size: 14px;
                margin-left: 30px;
            }
        }
    }
    .content-box{
        width: 100%;
        height: 1px;
        flex: 1;
        margin-top: 40px;
        display: flex;
        .update-box{
            width: 250px;
            height: 100%;
            display: flex;
            flex-direction: column;
            .form-box{
                width: 100%;
            }
            .tree-box{
                width: 100%;
                height: 1px;
                flex: 1;
                overflow: hidden;
                overflow-y: auto;
                padding-right: 20px;

                .custom-tree-node{
                    flex: 1;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    font-size: 14px;
                    padding: 3px 0;
                    padding-right: 20px;
                    .text-block{
                        flex: 1;
                        width: 1px;
                        white-space: nowrap;
                        overflow: hidden;
                        text-overflow: ellipsis;
                        padding-right: 10px;
                    }
                }
            }
        }
        .map-box{
            width: 1px;
            flex: 1;
            height: 100%;
        }
    }
}
</style>