<template>
    <div class="flex justify-start flex-wrap items-center">
        <DateTimeSelector v-model="date" range></DateTimeSelector>
        <q-btn @click="search">查询</q-btn>
    </div>
    <div class="flex justify-end flex-wrap items-center p-1">
        <q-toggle
            label="卫星地图"
            v-model="layers.satellite.show"
            color="primary"
            @update:model-value="toggleSatellite"
            keep-color
        />

        <q-toggle
            label="路网"
            v-model="layers.roadNet.show"
            color="primary"
            @update:model-value="toggleRoadNet"
            keep-color
        />

        <q-toggle
            label="实时交通"
            v-model="layers.traffic.show"
            color="primary"
            @update:model-value="toggleTraffic"
            keep-color
        />

        <q-toggle
            label="纠偏路线"
            v-model="feature.showFixed"
            color="primary"
            @update:model-value="fixedLocation"
            keep-color
        />
    </div>
    <div id="container"></div>
</template>
<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
import {reactive, ref} from "vue";
import DateTimeSelector from "matrix-middle-service-web/src/components/DateTimeSelector.vue";
import {useQuasar} from "quasar";
import moment from "moment";
const $q = useQuasar();
const COLOR = [
    '#6090e0', '#30c030', '#d070d0', '#80c0f0', '#f07050', '#ffb900',
    '#37a2da', '#ffdb5c', '#8378ea', '#e7bcf3', '#32c5e9', '#67e0e3',
    '#dd6b66', '#759aa0', '#e69d87', '#8dc1a9', '#ea7e53', '#eedd78',
]
let canvasDir = document.createElement('canvas')
let width = 24;
let height = 24;
canvasDir.width = width;
canvasDir.height = height;
let context = canvasDir.getContext('2d');
context.strokeStyle = 'white';
context.lineJoin = 'round';
context.lineWidth = 8;
context.moveTo(-4, width - 4);
context.lineTo(width / 2, 6);
context.lineTo(width + 4, width - 4);
context.stroke();
const date = ref({
    from: moment().startOf('d').format("YYYY-MM-DD HH:mm:ss"),
    to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
const feature = reactive({
    showFixed: false
})
// 地图实例 和 数据不要交给 vue 管理 否则性能大打折扣 且 会有各种奇葩问题
let map = {}
const data = {
    data: [],
    polyline: {},
    polylines: [],
    fixedPolyline: {},
    labelsLayer: {},
    markers: [],
    tmpMarker: {},
}
const layers = reactive({
    satellite: {
        inst: {},
        show: true,
    },
    roadNet: {
        inst: {},
        show: false,
    },
    traffic: {
        inst: {},
        show: false,
    }
})
function toggleSatellite(){
    if (layers.satellite.show) {
        layers.satellite.inst.show()
    } else {
        layers.satellite.inst.hide()
    }
}
function toggleRoadNet() {
    if (layers.roadNet.show) {
        layers.roadNet.inst.show()
    } else {
        layers.roadNet.inst.hide()
    }
}
function toggleTraffic() {
    if (layers.traffic.show) {
        layers.traffic.inst.show()
    } else {
        layers.traffic.inst.hide()
    }
}

AMapLoader.load({
    "key": "e01d7df3a4c3a1b8f06fa4544ddbbe9c",              // 申请好的Web端开发者Key，首次调用 load 时必填
    "version": "2.0",   // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    "plugins": [
        "AMap.Scale",
        "AMap.HawkEye",
        "AMap.ToolBar",
        "AMap.ControlBar"
    ],           // 需要使用的的插件列表，如比例尺'AMap.Scale'等
}).then((AMap) => {
    let scale = new AMap.Scale({
        visible: true
    })
    let toolBar = new AMap.ToolBar({
        visible: true,
        position: {
            top: '110px',
            right: '40px'
        }
    })
    let controlBar = new AMap.ControlBar({
        visible: true,
        position: {
            top: '10px',
            right: '10px'
        }
    })

    map = new AMap.Map('container',{
        zoom: 14,
    });
    console.log("地图对象", map)
    map.on("moveend",()=>{
        let bounds = map.getBounds()
        data.markers.forEach(marker=>{
            if(bounds.contains(marker.getPosition())) {
                marker.show()
            } else {
                marker.hide()
            }
        })
    })

    map.addControl(scale)
    map.addControl(toolBar)
    map.addControl(controlBar)

    // 卫星
    layers.satellite.inst = new AMap.TileLayer.Satellite({
        visible: layers.satellite.show,
    })
    // 路网
    layers.roadNet.inst = new AMap.TileLayer.RoadNet({
        visible: layers.roadNet.show,
        index: 10
    })
    // 实时交通
    layers.traffic.inst = new AMap.TileLayer.Traffic({
        zIndex: 11,
        visible: layers.traffic.show,
    });

    map.addLayer(layers.satellite.inst)
    map.addLayer(layers.roadNet.inst)
    map.addLayer(layers.traffic.inst)

}).catch(e => {
    $q.notify({
        position: "top",
        color: 'negative',
        message: "地图组件初始化失败",
        icon: 'report_problem'
    })
    console.log(e);
})

function search() {
    console.log(date.value)
    let params = {
        startTime: !date.value.from ? undefined : moment(date.value.from).format("YYYY-MM-DD HH:mm:ss"),
        endTime: !date.value.to ? undefined : moment(date.value.to).format("YYYY-MM-DD HH:mm:ss"),
    }
    map.remove(data.polylines)
    map.remove(data.polyline)
    map.remove(data.labelsLayer)
    map.remove(data.markers)

    let labelsLayer = new AMap.LabelsLayer({
        zooms: [3, 20],
        zIndex: 1000,
        // 该层内标注是否避让
        collision: true,
        // 设置 allowCollision：true，可以让标注避让用户的标注
        allowCollision: false,
    });
    data.labelsLayer = labelsLayer

    fetch("http://10.10.10.200:6573/record/location/get", {
        method: "POST",
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(params)
    }).then(resp => resp.json()).then(res => {
        let _data = res.data || []
        _data = _data.map(item=>{
            return {
                time: moment(item.locationTime),
                ...item,
            }
        })
        _data.sort((a,b)=>{
            return a.time.isBefore(b.time)?-1:1
        })
        data.data = _data
        console.log("data", _data)

        data.tmpMarker = new AMap.Marker({
            anchor: 'bottom-center',
            offset: [0, -15],
        });
        let markers = _data.filter((_, index) => index % 1 === 0).map((item, index) => {
            let text = {
                fontSize: 10,
                content: `时间:${item.locationTime}<br>速度: ${((item.speed || 0) * 3.6).toFixed(2)}km/h 方向角: ${(item.bearing || 0).toFixed(2)}°`
            }

            let marker = new AMap.LabelMarker({
                name: item.id,
                position: [item.longitude, item.latitude],
                zIndex: 10,
                icon: {
                    // 图标类型，现阶段只支持 image 类型
                    type: 'image',
                    // 图片 url
                    image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
                    // 图片尺寸
                    size: [6, 9],
                    // 图片相对 position 的锚点，默认为 bottom-center
                    anchor: 'bottom-center'
                },
                // text,
            })

            function show(e) {
                let position = e.data.data && e.data.data.position;

                if (position) {
                    data.tmpMarker.setContent(
                        `<div class="amap-info-window"
                                    style="padding: .75rem 1.25rem;font-size:12px;
                                    margin-bottom: 1rem;
                                    border-radius: .25rem;
                                    position: fixed;
                                    top: 1rem;
                                    background-color: white;
                                    width: auto;
                                    min-width: 22rem;
                                    border-width: 0;
                                    right: 1rem;
                                    box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);">`
                        + text.content +
                        '<div class="amap-info-sharp"></div>' +
                        '</div>');
                    data.tmpMarker.setPosition(position);
                    map.add(data.tmpMarker);
                }
            }

            function hide() {
                map.remove(data.tmpMarker);
            }

            marker.on('mouseover', (e)=>show(e));
            marker.on('touchstart', (e)=>show(e));
            marker.on('mouseout', ()=>hide());
            marker.on('touchend', ()=>hide());

            return marker;
        })
        data.markers = markers
        labelsLayer.add(markers)
        map.add(data.labelsLayer)

        let days = []
        let prev = moment(0)
        for (let i = 0; i < _data.length; i++) {
            let datum = _data[i]

            if (prev.year() === datum.time.year() && prev.month() === datum.time.month() && prev.date() === datum.time.date() ) {
                prev = datum.time
            } else {
                prev = datum.time
                days.push([])
            }
            days[days.length -1].push(datum)
        }

        let colorList = Array.from({ length: days.length })
            .map(() => COLOR[Math.floor(Math.random() * COLOR.length)]);
        data.polylines = []
        days.forEach((_data,index) => {
            let path = _data.map((item) => {
                return new AMap.LngLat(item.longitude, item.latitude)
            })

            let polyline = new AMap.Polyline({
                path: path,
                showDir: true,
                dirImg: canvasDir,
                borderWeight: 6, // 线条宽度，默认为 1
                strokeWeight: 6,
                strokeOpacity: 0.9, // 透明度
                strokeColor: colorList[index], // 线条颜色
                dirColor: 'white',
                lineJoin: 'round' // 折线拐点连接处样式})
            })
            data.polylines.push(polyline)
        })
        console.log("polylines",data.polylines)
        // polyline = new AMap.Polyline({
        //     path: path,
        //     showDir: true,
        //     dirImg: canvasDir,
        //     borderWeight: 6, // 线条宽度，默认为 1
        //     strokeWeight: 6,
        //     strokeColor: 'red', // 线条颜色
        //     dirColor: 'white',
        //     lineJoin: 'round' // 折线拐点连接处样式})
        // })
        map.add(data.polylines)
        setTimeout(()=>{
            if (data.polylines.length > 0) {
                map.setFitView()
            }
        })
        fixedLocation()
    })
}

function fixedLocation() {
    map.remove(data.fixedPolyline)

    if (!feature.showFixed) {
        return
    }

    let task = []
    let startTime
    let preFixedData = (data.data || []).map((item, index) => {
        if (index % 500 === 0) {
            startTime = data.data[0].time
        }

        let time = item.time
        return {
            x: item.longitude,
            y: item.latitude,
            sp: item.speed || 0,
            ag: item.bearing || 0,
            tm: index % 500 === 0 ? time.unix() : time.diff(startTime, 's')
        }
    })
    console.log("纠偏路线 预处理数据: ", preFixedData)

    let group = []
    let len = preFixedData.length
    for (let i = 0; i < Math.ceil(len / 500); i++) {
        group.push(preFixedData.splice(0, 500))
    }
    console.log("分组: ", group)

    task = group.map(item => {
        return new Promise(resolve => {
            AMap.plugin('AMap.GraspRoad', function () {
                let grasp = new AMap.GraspRoad();
                grasp.driving(item, function (error, result) {
                    if (error) {
                        resolve([])
                    }
                    if (!error) {
                        let newPath = result.data.points;//纠偏后的轨迹
                        let distance = result.data.distance;//里程

                        console.log("返回值 => ", "路径: ", newPath, "里程: ", distance)
                        resolve(newPath)
                    }
                })
            })
        })
    })

    Promise.all(task).then(paths => {
        let fixedData = paths.flat(1)
        console.log("纠偏路线数据: ", fixedData)

        data.fixedPolyline = new AMap.Polyline({
            path: fixedData.map(item => {
                return new AMap.LngLat(item.x, item.y)
            }),
            showDir: true,
            strokeColor: 'orange', // 线条颜色
            borderWeight: 6, // 线条宽度，默认为 1
            strokeWeight: 6,
        })
        map.add(data.fixedPolyline)
    })
}
</script>

<style scoped lang="scss">
#container {
    width: 100vw;
    height: 80vh;
}
</style>
