import axios from "axios";
import { gcj02towgs84, wgs84togcj02 } from 'coordtransform'
import * as turf from '@turf/turf'
import { Url } from "../../../utils/urlFormat";
import { getMethodCommon } from "../../../api/common";
import { parse } from "../lib/handleGeojson";
import { deepClone } from "../../../utils";
import { Message } from "element-ui";

const urls = new Url()
const GD_URL = "https://restapi.amap.com/v5/direction/driving"
const GD_KEY = "6af6a87038f44c8c793aa70331f2b7ca"


//路线的图层
let pathGraphicLayers = null

//导航寻路
export const getRouterFunc = (params, method = 'all') => {
    
    /**
     * method：
     *     当为 postgis时，仅仅使用postgis导航
     *     默认：all  :高德 + postgis
     *     gaode:高德
     */

    let { startlng, startlat, endlng, endlat } = params

    if (method == 'postgis') {
        //使用gpostgis进行导航
        return new Promise((resolve, reject) => {
            let postgisParams = {
                startlng: startlng,
                startlat: startlat,
                endlng: endlng,
                endlat: endlat,
                areaname: localStorage.getItem("areaName"),
            }
            getRouterByPostGis(postgisParams).then(geojson => {
                //postGisCoordinates:postgis返回的geojson取出坐标数组
                let postGisCoordinates = getOneLineCoordinatesFromGeometry(geojson)
                let startRouterLngLat = postGisCoordinates[0]
                let endRouterLngLat = postGisCoordinates.at(-1)
                let resObject = {
                    allCoordinates: postGisCoordinates, //全部线路的合集
                    postGisRoute: postGisCoordinates, // postgis线路
                    gdRoute: [],
                    startLngLat: [startlng, startlat],  // 起点
                    endLngLat: [endlng, endlat],    //终点
                    startRouterLngLat: startRouterLngLat, // 路线查询结果的起点
                    endRouterLngLat: endRouterLngLat,   //路线查询结果的终点
                }
                let simpleRoute = getMinimumRoute(resObject)
                resolve(simpleRoute)
            })
        }).catch(err => {

        })
    }
    if (method == 'all') {
        // 先用高德进行导航
        return new Promise((resolve, reject) => {
            getRouterByGD(params).then(solution => {
                // solution 为多条线路的数组，现在先用第一条线路  solution.path[0]
                let gdRoute = solution.path[0]
                let postgisParams = {
                    startlng: gdRoute.endCoordinates[0],
                    startlat: gdRoute.endCoordinates[1],
                    endlng: endlng,
                    endlat: endlat,
                    areaname: localStorage.getItem("areaName"),
                }

                console.log("postgisParams",postgisParams);
                //使用gpostgis求出剩下的路线
                getRouterByPostGis(postgisParams).then(geojson => {
                    //postGisCoordinates:postgis返回的geojson取出坐标数组
                    
                    let postGisCoordinates = getOneLineCoordinatesFromGeometry(geojson)
                    // 高德返回的第一条线路的坐标数组
                    let path_gd = gdRoute.path_polyline
                    //合并高德和postgis的路线
                    let allCoordinates = path_gd.concat(postGisCoordinates)
                    //导航线路的起点和终点
                    let startRouterLngLat = allCoordinates[0]
                    let endRouterLngLat = allCoordinates.at(-1)
                    let resObject = {
                        allCoordinates: allCoordinates, //全部线路
                        gdRoute: path_gd,   //高德的线路
                        postGisRoute: postGisCoordinates,   // postgis的线路
                        startLngLat: [startlng, startlat],  // 起点
                        endLngLat: [endlng, endlat],    //终点
                        startRouterLngLat: startRouterLngLat, // 路线查询结果的起点
                        endRouterLngLat: endRouterLngLat,   //路线查询结果的终点
                    }
                    let simpleRoute = getMinimumRoute(resObject)
                    resolve(simpleRoute)
                })
            })
        })
    }
}




//高德路线规划
export const getRouterByGD = (params) => {
    /**
     * type:Object
     */
    let { startlng, startlat, endlng, endlat } = params
    //wgs84转火星坐标系
    var gcj02StartLngLat = wgs84togcj02(startlng, startlat);
    var gcj02EndLngLat = wgs84togcj02(endlng, endlat);
    let gd_params = {
        origin: `${gcj02StartLngLat[0]},${gcj02StartLngLat[1]}`,
        destination: `${gcj02EndLngLat[0]},${gcj02EndLngLat[1]}`,
        show_fields: 'polyline',
        key: GD_KEY
    }
    let new_url = urls.getUrl(GD_URL, gd_params)
    return new Promise((resolve, reject) => {
        axios({
            method: "get",
            url: new_url,
        }).then((res) => {
            if (res.status === 200) {
                let solution = []
                //处理数据
                res.data.route.paths.map(path => {
                    let route_len = path.distance
                    let path_polyline = path.steps.map(step => {
                        return step.polyline
                    })
                    let router_path_str = [] //暂时存放 ['117.927498,35.263264']
                    path_polyline.forEach(polyline => {
                        let step = polyline.split(';')
                        router_path_str = router_path_str.concat(step)
                    });
                    // 去掉重复点
                    let unique_router_path_str = [...new Set(router_path_str)]
                    // 坐标转数组
                    let unique_router_path = unique_router_path_str.map(path_str => {
                        let lng_lat_list = path_str.split(',')
                        //高德坐标系转wgs84坐标系
                        var wgs84Coordinate = gcj02towgs84(...lng_lat_list);
                        return wgs84Coordinate
                    })
                    //高德导航的起点和终点
                    let startCoordinates = unique_router_path[0]
                    let endCoordinates = unique_router_path.at(-1)
                    // 高德地图返回的结果：方案一。长度，线
                    solution.push(
                        {
                            route_len: route_len,
                            path_polyline: unique_router_path,
                            startCoordinates: startCoordinates,
                            endCoordinates: endCoordinates
                        }
                    )
                })
                let result = {
                    routerCount: parseInt(res.data.count),
                    path: solution
                }
                resolve(result)
            } else {
                reject(res)
            }
        }).catch(err => {
            reject(err)
        })
    })
}

//使用postgres + postgis寻路
export const getRouterByPostGis = (params) => {
    return new Promise((resolve, reject) => {
        getMethodCommon("/FirePrevention/LoadRoad", params).then((res) => {
            if (res.data.length > 0) {
                let LineString = res.data[0].route;
                if (LineString == null || LineString == "null") {
                    //没有找到路线，返回空
                    console.log('PostGIS未找到合适了路线')
                    // Message.warning({message:"未找到合适的路线"});
                    resolve(parse(null))
                } else {
                    resolve(parse(LineString))
                }
            } else {
                // Message.warning({message:"未找到合适的路线"})
                console.log('PostGIS未找到合适了路线')
                resolve(parse(null))
            }
        }).catch(err => {
            // Message.warning({message:"未找到合适的路线"})
            console.log('PostGIS寻路算法服务端错误')
            resolve(parse(null))
        })
    })
}

// 绘制线路
export const drawRouterFunc = (pathObject,type=false) => {

    
    let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObject
    // 添加graphic
    if (pathGraphicLayers == null) {
        pathGraphicLayers = new mars3d.layer.GraphicLayer();
        window.globalmap.addLayer(pathGraphicLayers);
    } else {
        pathGraphicLayers.clear();
    }
    //当只有两组数据时，说明没有导航的路线，直接使用虚线连接
    if (allCoordinates.length == 2) {
        //只绘制开头到结尾的路线的路段
        let endPathGraphic = drawPolylineDashEntity([startLngLat, endLngLat], 'YELLOW')
        pathGraphicLayers.addGraphic(endPathGraphic);
    } else {
        // 导航数据路段
        let pathGraphic = drawLineFlowEntity(allCoordinates, 'CYAN')
        let gdPathGraphic = drawLineFlowEntity(gdRoute, 'YELLOW')
        let postgisPathGraphic = drawLineFlowEntity(postGisRoute, 'YELLOW')

        //开始的路段
        let startPathGraphic = drawPolylineDashEntity([startLngLat, startRouterLngLat], 'YELLOW')

        //结尾的路段
        let endPathGraphic = drawPolylineDashEntity([endRouterLngLat, endLngLat], 'YELLOW')

        pathGraphicLayers.addGraphic(pathGraphic);
        // pathGraphicLayers.addGraphic(gdPathGraphic);
        // pathGraphicLayers.addGraphic(postgisPathGraphic);
        pathGraphicLayers.addGraphic(startPathGraphic);
        pathGraphicLayers.addGraphic(endPathGraphic);
    }
}

// 生成虚线实体
const drawPolylineDashEntity = (positions, cesiumColor) => {
    return new mars3d.graphic.PolylineEntity({
        positions: positions,
        style: {
            width: 5,
            clampToGround: true,
            materialType: mars3d.MaterialType.PolylineDash,
            materialOptions: {
                color: Cesium.Color[cesiumColor],
                dashLength: 8.0,
            },
        },
    });
}
// 生成动态线实体
const drawLineFlowEntity = (positions, cesiumColor) => {
    return new mars3d.graphic.PolylineEntity({
        positions: positions,
        style: {
            width: 5,
            clampToGround: true,
            materialType: mars3d.MaterialType.LineFlow,
            materialOptions: {
                color: Cesium.Color[cesiumColor],
                image: "/img/line-colour.png",
                speed: 10,
            },
        },
    });
}



//删除路线
export const clearRouterFunc = () => {
    if (pathGraphicLayers == null) {
        return false
    } else {
        pathGraphicLayers.clear();
    }
}

//计算最近路线
const getMinimumRoute = (pathObject) => {
    //备份Object
    let pathObjectClone = deepClone(pathObject)
    let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObjectClone
    console.log("pathObject",pathObject);
    // 当只有一个点时（终点），说明高德地图和postgis都未查询到线路，直接返回两点
    if (allCoordinates.length <= 1) {
        pathObjectClone.allCoordinates = [startLngLat, endLngLat]
        return pathObjectClone
    }
    //当postgis寻路时，计算两条线路的重叠之处
    if (postGisRoute.length && gdRoute.length) {
     

        
        //实例化turf标准格式

        let gdRouteLine = null;

        if(gdRoute.length == 1 && typeof gdRoute[0] == 'object'){
            gdRoute[1] = [];
            
        }
        gdRouteLine = turf.lineString(gdRoute);

        let postGisRouteLine = turf.lineString(postGisRoute);
        //获取postgis和高德寻路的所有交点
        let intersectsGeojson = turf.lineIntersect(gdRouteLine, postGisRouteLine);
        let intersectsCoordinates = getMultPointCoordinatesFromGeoJson(intersectsGeojson)
        //如果相交点大于1，说明路线有重复部分
        if (intersectsCoordinates.length > 1) {
            let lastIntersectsCoordinates = intersectsCoordinates[0]
            let [slicedGdCoordinates, slicedPostGisCoordinates] = sliceByPoint(startRouterLngLat, gdRouteLine, endRouterLngLat, postGisRoute, lastIntersectsCoordinates)
            allCoordinates = slicedGdCoordinates.concat(slicedPostGisCoordinates)
            //处理后的结果赋值给pathObjectClone
            pathObjectClone.gdRoute = slicedGdCoordinates
            pathObjectClone.postGisRoute = slicedPostGisCoordinates
            gdRouteLine = turf.lineString(slicedGdCoordinates);
            postGisRouteLine = turf.lineString(slicedPostGisCoordinates);
        }
        // 阈值计算重复路线，去除重复线路
        let overlapping = turf.lineOverlap(gdRouteLine, postGisRouteLine, { tolerance: 0.1 });
        if (overlapping.features.length) {
            let lastOverlapPoint = overlapping.features.at(-1).geometry.coordinates[0]
            let [overlapGdCoordinates, overlapPostGisCoordinates] = sliceByPoint(startRouterLngLat, gdRouteLine, endRouterLngLat, postGisRoute, lastOverlapPoint)
            allCoordinates = overlapGdCoordinates.concat(overlapPostGisCoordinates)
        }

    }
    // 转成turf标准线格式
    let allRouteLine = turf.lineString(allCoordinates);
    // 转成turf标准点格式
    let startLngLatPoint = turf.point(startLngLat);
    let startRouterLngLatPoint = turf.point(startRouterLngLat);
    let endLngLatPoint = turf.point(endLngLat);
    let endRouterLngLatPoint = turf.point(endRouterLngLat);
    //获取终点到导航线最近的点
    let snappedGeojson = turf.nearestPointOnLine(allRouteLine, endLngLatPoint, { units: 'miles' });
    let snappedCoordinates = getOnePointCoordinatesFromGeoJson(snappedGeojson)
    // 根据最近的点截取路线，取前半部分
    let slicedGeojson = turf.lineSlice(startRouterLngLat, turf.point(snappedCoordinates), allRouteLine);
    let slicedCoordinates = getOnePointCoordinatesFromGeoJson(slicedGeojson)
    //把截取后的路线赋值给pathObjectClone
    pathObjectClone.allCoordinates = slicedCoordinates
    //计算出发地到目的地的图上距离（直线）
    let distanceStartToEnd = turf.distance(startLngLatPoint, endLngLatPoint)
    //计算出发点到出发导航路线出发点的步行距离
    let distanceStartToStartRoute = turf.distance(startLngLatPoint, startRouterLngLatPoint)
    console.log("计算出发点到出发导航路线出发点的步行距离",distanceStartToStartRoute);
    //计算终点到出发导航路线终点的步行距离
    let distanceEndToEndRoute = turf.distance(endLngLatPoint, endRouterLngLatPoint)
    console.log("计算终点到出发导航路线终点的步行距离",distanceEndToEndRoute);
    //如果出发点与目的地的实际距离小于步行的距离，直接使用出发点到目的地的距离，导航此时不适用
    if (distanceStartToEnd < (distanceStartToStartRoute + distanceEndToEndRoute)) {
        pathObjectClone.allCoordinates = [startLngLat, endLngLat]
    }
    //把终点到导航终点改为距离线路的最近的的点
    pathObjectClone.endRouterLngLat = snappedCoordinates
    return pathObjectClone
}

const sliceByPoint = (line1Start, line1, line2End, line2, point) => {
    /**
     * 根据点point把line1的前半部分和line2的后半部分进行拼接
     * line1Start:line1的起始点 [lng.lat]
     * line2End:line2 的终止点 [lng,lat]
     */
    //拷贝line2的坐标数组进行倒序排列
    let line2Copy = [...line2]
    line2Copy.reverse()
    let line2CopyReverseLineString = turf.lineString(line2Copy);
    // 根据point截取路线，line1取前半部分
    // 根据point截取路线，line2取后半部分
    //然后将两部分拼接，让line1路线从第一个交点处转向line2路段
    let slicedLine1Geojson = turf.lineSlice(line1Start, turf.point(point), line1);
    let slicedLine1Coordinates = getOnePointCoordinatesFromGeoJson(slicedLine1Geojson)
    let slicedLine2Geojson = turf.lineSlice(line2End, turf.point(point), line2CopyReverseLineString);
    let slicedLine2Coordinates = getOnePointCoordinatesFromGeoJson(slicedLine2Geojson)
    slicedLine2Coordinates.reverse()
    return [slicedLine1Coordinates, slicedLine2Coordinates]
}


// 坐标转geoJson
const comLineStringGeoJson = (coordinates) => {
    return {
        "type": "Feature",
        "properties": {},
        "geometry": {
            "coordinates": coordinates,
            "type": "LineString"
        }
    }
}
// 从一条线的geometry中获取坐标
const getOneLineCoordinatesFromGeometry = (geometry) => {
    if(geometry){
        let coordinates = geometry.coordinates
        let list = []
        if (geometry.type == "MultiLineString") {
            coordinates.map(coord => {
                list = list.concat(coord)
            })
        } else if (geometry.type == 'LineString') {
            list = list.concat(geometry.coordinates)
        } else {
            list = []
        }

        return list
    }else{
        return [];
    }
    

}
//从一个点的geojson中返回坐标点
const getOnePointCoordinatesFromGeoJson = (geojson) => {
    return geojson.geometry.coordinates
}
//从多个点的geojson中返回坐标点
const getMultPointCoordinatesFromGeoJson = (geojson) => {
    console.log('geojson::: ', geojson);
    return geojson.features.map(feature => {
        return feature.geometry.coordinates
    })

}


// 全局漫游
let carGraphicEntity = null;
let carGraphicLayer = null;

export const handlerStartRoaming = (coordinates,roaming=true)=>{
    if(carGraphicLayer == null){
        carGraphicLayer = new mars3d.layer.GraphicLayer();
        window.globalmap.addLayer(carGraphicLayer);
    }else{
        carGraphicLayer.clear();
    }

    carGraphicEntity = new mars3d.graphic.FixedRoute({
        name: "步行路线",
        frameRate: 1,
        speed: 500,
        autoStop: false, // 到达终点自动停止
        clockLoop: true, // 循环播放
        positions: coordinates,
        pauseTime: 0,
        camera: {
            type: "gs",
            radius: 2500
        },
        model: {
            // url: "//data.mars3d.cn/gltf/mars/car/bus3.gltf",
            url:"/cartoon_fire_truck/xiaofangche.gltf",
            scale: 5,
            minimumPixelSize: 50,
            clampToGround: true
        },
        circle: {
            radius: 10,
            materialType: mars3d.MaterialType.CircleWave,
            materialOptions: {
                color: "#ffff00",
                opacity: 0.3,
                speed: 10,
                count: 3,
                gradient: 0.1
            },
            clampToGround: true
        }
    })
    carGraphicLayer.addGraphic(carGraphicEntity)
    // 开始漫游
    carGraphicEntity.enabled = roaming;
    carGraphicEntity.start()
}

export const handlerStopRoaming = ()=>{
    if(carGraphicEntity){
        carGraphicLayer.removeGraphic(carGraphicEntity);
        carGraphicEntity = null;
    }
}

