import API from "@/api"

let data_source = null

function tree2list(tree, list = []) {
    tree.forEach(item => {
        if (item.devices && item.devices.length) {
            item.devices.forEach(d => list.push(d))
        }
        if (item.child && item.child.length) {
            let arr = tree2list(item.child)
            arr.forEach(d => list.push(d))
        }
    })
    return list
}

function tree2list_org(tree, list = []) {
    tree.forEach(item => {
        list.push(item)
        if (item.child && item.child.length) {
            // 为了不失去引用，所以写成遍历然后 push
            let arr = tree2list_org(item.child)
            arr.forEach(_item => list.push(_item))
        }
    })
    return list
}

export default {

    async init_data_source() {
        data_source = new Cesium.CustomDataSource("FCKERNEL_LAYER")
        await viewer.dataSources.add(data_source)
    },
    destroy_data_source() {
        if (data_source) {
            data_source.entities.removeAll()
            viewer.dataSources.remove(data_source, true)
            data_source = null
        }
    },

    async list() {
        let list = await API.FCKERNEL.ListUAV()
        if (list && list.length && list[0].child) {
            list[0].child.sort(function (a, b) {
                return a.sort - b.sort
            })
        }

        function each(tree, flag) {
            return tree.map((item) => ({
                ...item,
                collapse: flag,
                devices:
                    item.devices && item.devices.length
                        ? item.devices.map((device) => ({
                            ...device,
                            _location: false,
                            _video: false,
                            _airway: false,
                            _control: false,
                            org_id: item.id,
                            // reportStatus: 1
                        }))
                        : [],
                child: item.child && item.child.length ? each(item.child, true) : [],
            }));
        }

        if (list && list.length) {
            list = each(list)
        }
        this.uav.list = list || []
    },

    subscribe(topic, callbck) {
        this.mqtt_subscribe(topic, callbck)
    },

    async fn(cate, device) {
        if (device.reportStatus !== 1) {
            this.$message('无人机不在线');
            return
        }

        if (!data_source) {
            await this.uav_init_data_source()
        }
        let uavCate=device.cateName=='px4'?'PX4':'APM'
        let topic = `${uavCate}/RECEIVE/${device.deviceHardId}`
        this.uav_subscribe(topic, () => {
            console.log(`订阅无人机数据：topic:${topic}`);
        })

        if (cate === 1) {
            // 定位
            device._location = !device._location
            if (device._location) {
                this.uav_show_location(device)
            } else {
                this.uav_hide_location(device)
            }
        } else if (cate === 2) {
            // 航线uavData
            device._airway = !device._airway
            if (device._airway) {
                this.uav_show_airway(device)
            } else {
                this.uav_hide_airway(device)
            }
        } else if (cate === 3) {
            device._video = !device._video
            if (device._video) {
                console.log(device,'device')
                this.uav_show_video(device)
            } else {
                this.uav_hide_video(device)
            }
        } else if (cate === 4) {
            // 控制面板
            device._control = !device._control
            if (device._control) {
                this.uav_show_control(device)
            } else {
                this.uav_hide_control(device)
            }
        }
    },

    trans_location_data(device, uav_data) {
        if (!uav_data) {
            return uav_data
        }
        let uavInfo = uav_data.uavInfo
        let position = Cesium.Cartesian3.fromDegrees(
            uavInfo.longitude * 1,
            uavInfo.latitude * 1,
            uavInfo.altitude * 1
        );
        let yaw = Cesium.Math.toRadians(uavInfo.yaw + 90),
            pitch = Cesium.Math.toRadians(uavInfo.pitch),
            roll = Cesium.Math.toRadians(uavInfo.roll),
            hpr = new Cesium.HeadingPitchRoll(yaw, pitch, roll),
            orientation = Cesium.Transforms.headingPitchRollQuaternion(
                position,
                hpr
            );

        let positions = [];
        if (uavInfo.longitude != 0 && uavInfo.latitude != 0) {
            positions.push(position);
        }
        return {
            position,
            positions,
            orientation,
            device
        };
    },

    trans_mqtt_location_data(device, uav_data) {
        if (!uav_data) {
            return uav_data
        }

        let location = uav_data.locationCoordinate3D
        let position = Cesium.Cartesian3.fromDegrees(
            location.longitude * 1,
            location.latitude * 1,
            location.altitude * 1
        );

        let attitude = uav_data.attitude
        let yaw = Cesium.Math.toRadians(attitude.yaw + 90),
            pitch = Cesium.Math.toRadians(attitude.pitch),
            roll = Cesium.Math.toRadians(attitude.roll),
            hpr = new Cesium.HeadingPitchRoll(yaw, pitch, roll),
            orientation = Cesium.Transforms.headingPitchRollQuaternion(
                position,
                hpr
            );

        let positions = [];
        if (location.longitude != 0 && location.latitude != 0) {
            positions.push(position);
        }
        return {
            position,
            positions,
            orientation,
            device
        };
    },

    async show_location(device) {
        let uav_data = await API.FCKERNEL.GetLastUavData({
            deviceHardId: device.deviceHardId
        })

        if (!uav_data) {
            this.$el_message("暂未找到位置信息", () => { }, "error")
            return uav_data
        }

        if (!data_source) {
            return false
        }

        let devices = tree2list(this.uav.list)
        devices.map(item => item.deviceHardId != device.deviceHardId && (item._location = false))
        let { deviceHardId } = device
        let cesium_layer = this.g_cesium_layer()
        let data = this.uav_trans_location_data(device, uav_data)
        let entities = data_source.entities
        let model = entities.getById(`fckernel_model_${deviceHardId}`)
        if (!model) {
            this.uav.online[deviceHardId] = data
            this.uav.online[deviceHardId].entity_id = `fckernel_model_${data.device.deviceHardId}`
            model = cesium_layer.add_model(entities, this.uav.online[deviceHardId])
        }

        let polyline = entities.getById(`fckernel_polyline_${deviceHardId}`)
        if (!polyline) {
            cesium_layer.add_polyline(entities, {
                ...data,
                entity_id: `fckernel_polyline_${data.device.deviceHardId}`,
                options: {
                    show: false
                }
            })
        }

        viewer.camera.flyTo({
            destination: model.position.getValue(Cesium.JulianDate.now()),
            maximumHeight: 10,
            complete: () => {
                viewer.trackedEntity = model;
            }
        })
    },
    hide_location(device, uav_data) {
        viewer.trackedEntity = null
    },
    update_location(device, uav_data) {
        let online = this.uav.online[device.deviceHardId]
        if (online) {
            let data = this.uav_trans_mqtt_location_data(device, uav_data)
            online.orientation = data.orientation
            online.position = data.position
            online.positions.push(online.position)
            online.position = data.position
        }
    },

    show_airway(device) {
        if (!data_source) {
            return false
        }
        let entities = data_source.entities
        if (!device._location) {
            device._location = true
            this.uav_show_location(device)
        }
        let entity = entities.getById(`fckernel_polyline_${device.deviceHardId}`)
        entity && (entity.polyline.show = true)
    },
    hide_airway(device) {
        if (!data_source) {
            return false
        }

        let entities = data_source.entities
        let entity = entities.getById(`fckernel_polyline_${device.deviceHardId}`)
        entity && (entity.polyline.show = false)
    },

    async show_video(device) {
        let data = await API.FCKERNEL.GetVideoByDeviceHardId({id:device.id,onLine:1})
        let index = this.uav.videos.findIndex(item => item === undefined)
        if (index !== -1) {
            this.uav.videos.splice(index, 1, {
                ...device,
                videos: data,
            })
        } else {
            if (this.uav.videos.length < 4) {
                this.uav.videos.push({
                    ...device,
                    videos: data,
                })
            } else {
                this.uav_hide_video(this.uav.videos[0])
                this.uav_show_video(device, uav_data)
            }
        }
    },
    hide_video(device) {

        let { deviceHardId } = device
        let index = this.uav.videos.findIndex(item => item && (item.deviceHardId === deviceHardId))

        let devices = tree2list(this.uav.list)
        device = devices.find(item => item.deviceHardId === deviceHardId)

        if (index !== -1) {
            device._video = false
            this.uav.videos.splice(index, 1)
        }
    },

    show_control(device) {
        // 先清空所有无人机控制的状态
        let device_list = tree2list(this.uav.list)
        device_list.forEach(item => {
            if ((item.deviceHardId !== device.deviceHardId) && item._control) {
                item._control = false
                this.uav_hide_control(item)
            }
        })

        this.$set(this.uav.control, "device", device)
    },
    hide_control(device) {
        this.uav.control.device = null
        this.uav.control.device = null
        this.uav.control.data = null
        this.uav.control.battery = null
        this.uav.control.mount = null
        this.uav.control.mounts = []
        this.uav.control.mounts = []

    },
    update_control(device, uav_data) {
        let control_device = this.uav.control.device
        if (control_device && control_device.deviceHardId === device.deviceHardId) {
            this.$set(this.uav.control, "data", uav_data)
        }
    },

    update_control_battery(device, battery_data) {
        let control_device = this.uav.control.device
        if (control_device && control_device.deviceHardId === device.deviceHardId) {
            this.$set(this.uav.control, "battery", battery_data)
        }
    },
    // 无人机提示信息
    update_control_info(device, battery_data) {
        let control_device = this.uav.control.device
        if (control_device && control_device.deviceHardId === device.deviceHardId) {
            this.uav.info.push(battery_data)
        }
    },

    update_mount(device, data) {
        let control_device = this.uav.control.device
        if (control_device && control_device.deviceHardId === device.deviceHardId) {
            let mount = this.mount.list.find(item => item.name === data.gimbalName)
            if (mount) {
                let find_item = this.uav.control.mounts.find(item => item.name === data.gimbalName)
                if (!find_item) {
                    this.uav.control.mounts.push({
                        ...data,
                        ...mount
                    })
                }
            }
        }
    },
    change_mount(mount) {
        this.$set(this.uav.control, "mount", mount)
        console.log('mount',this.uav);
    },
    mount_directive(data) {
        let mount = this.uav.control.mount
        if (mount) {
            this.uav_mqtt_fn({
                type: 514,
                data: {
                    mountId: mount.mountId,
                    payload: data
                }
            })
        }
    },

    /**
     * 切换无人机模式
     * { type: 513, data: mode }
     * @param {*} data 
     */
    change_mode(mode) {
        this.uav_mqtt_fn({ type: 513, data: mode.data })
    },

    update_org_status(cate, id) {
        let list = tree2list_org(this.uav.list)
        let org_id = id
        while (org_id) {
            let org = list.find(x => x.id === org_id)
            if (org) {
                if (cate === 1) {
                    org.offline -= 1;
                    org.online += 1;
                }
                if (cate === 0) {
                    org.offline += 1;
                    org.online -= 1;
                }
                org_id = org.pid
            } else {
                org_id = null
            }
        }
    },

    /**
     * cate { -1: 离线, 1: 上线 }
     * @param {*} cate 
     * @param {*} deviceHardId 
     */
    update_device_report_status(cate, deviceHardId) {
        let devices = tree2list(this.uav.list)
        let did = this.uav.control.device && this.uav.control.device.deviceHardId
        devices.map(item => {
            if (item.deviceHardId == deviceHardId) {
                if (item.reportStatus !== cate) {
                    item.reportStatus = cate
                    if (cate === 1) {
                        this.uav_update_org_status(1, item.org_id)
                    } else if (cate == 0) {
                        this.uav_update_org_status(0, item.org_id)
                        item._control = false
                        // // 视频推流状态关闭
                        // item._videoStatus = 0
                        if (did && (did == deviceHardId)) {
                            this.uav.control = {}
                        }
                    }
                }
            }
        })
    },

    /**
     * 无人机 mqtt 发送指令
     * @param {*} data 
     */
    mqtt_fn(data) {
        console.log(data,'111');
        let device = this.uav.control.device
        if (device) {
            // let obtain_topic = device.topic.replace("receive", "obtain")
            let uavCate = device.cateName == 'px4' ? 'PX4' : 'APM'
            let topic = `${uavCate}/OBTAIN/${device.deviceHardId}`
            this.mqtt_publish(topic, data, e => {
            })
        }
    },
}