import { Ref } from 'vue'

import * as Cesium from 'mars3d-cesium'
import * as mars3d from 'mars3d'

// 定义类型
export type Cesium = typeof Cesium

// 服务域名
const tdtUrl = 'https://t{s}.tianditu.gov.cn/'
// 服务负载子域
const subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']

/**
 * 资源服务器地址
 */
export const host = 'http://192.168.0.156'

// 天地图 token
export const token = 'aa0ccd36f2dbb86dbb16cbf63f0034a6'

interface MarsMapConfig {
    scene?: mars3d.Map.sceneOptions
    control?: mars3d.Map.controlOptions
    mouse?: mars3d.Map.mouseOptions
    effect?: mars3d.Map.effectOptions
    terrain?: mars3d.Map.terrainOptions
    basemaps?: mars3d.Map.basemapOptions[]
    layers?: mars3d.Map.layerOptions[]
    chinaCRS?: mars3d.ChinaCRS
    lang?: mars3d.LangType
    templateValues?: any
    token?: mars3d.Map.tokenOptions
}

export const config: MarsMapConfig = {
    basemaps: [{ name: '天地图', type: 'tdt', layer: 'img_d', show: true }],
    scene: {
        center: { lat: 30.054604, lng: 108.885436, alt: 22000000, heading: 0, pitch: -90 },
        // center: {
        //     lat: 30.48564,
        //     lng: 112.86168,
        //     alt: 350,
        //     heading: 180,
        //     pitch: -25,
        //     roll: 0,
        // },
        scene3DOnly: false,
        shadows: false,
        removeDblClick: true,
        sceneMode: 3,
        showSun: true,
        showMoon: true,
        showSkyBox: true,
        showSkyAtmosphere: true,
        fog: true,
        fxaa: true,
        requestRenderMode: true,
        globe: {
            depthTestAgainstTerrain: false,
            baseColor: '#546a53',
            showGroundAtmosphere: true,
            enableLighting: false,
        },
        cameraController: {
            zoomFactor: 3.0,
            minimumZoomDistance: 1,
            maximumZoomDistance: 50000000,
            enableRotate: true,
            enableTranslate: true,
            enableTilt: true,
            enableZoom: true,
            enableCollisionDetection: true,
            minimumCollisionTerrainHeight: 15000,
        },
    },
    control: {
        homeButton: true,
        baseLayerPicker: true,
        sceneModePicker: true,
        vrButton: false,
        fullscreenButton: true,
        navigationHelpButton: true,
        animation: false,
        timeline: false,
        infoBox: false,
        geocoder: false,
        selectionIndicator: false,

        contextmenu: { hasDefault: true },
        mouseDownView: true,
        zoom: { insertIndex: 1 },
        compass: { bottom: 'toolbar', left: '5px' },
        distanceLegend: { left: '0px', bottom: '2px' },
        locationBar: {
            fps: true,
            format: "<div>经度:{lng}</div> <div>纬度:{lat}</div> <div>海拔：{alt}米</div> <div class='hide700'>层级：{level}</div><div>方向：{heading}°</div> <div>俯仰角：{pitch}°</div><div class='hide700'>视高：{cameraHeight}米</div>",
        },
    },
}

/**
 * 默认的 Cesium3DTileset 配置项
 */
export const defaultTilesetConfig = {
    show: true,
    backFaceCulling: true,
    maximumScreenSpaceError: 16,
    maximumMemoryUsage: 256,
    cullWithChildrenBounds: true,
    cullRequestsWhileMovingMultiplier: 10,
    dynamicScreenSpaceError: true,
    dynamicScreenSpaceErrorDensity: 0.00278,
    dynamicScreenSpaceErrorFactor: 4,
    dynamicScreenSpaceErrorHeightFalloff: 0.25,
    skipLevelOfDetail: true,
    baseScreenSpaceError: 1024,
    skipScreenSpaceErrorFactor: 16,
    skipLevels: 1,
    immediatelyLoadDesiredLevelOfDetail: false,
    loadSiblings: true,
    luminanceAtZenith: 0.2,
    preferLeaves: true,
    progressiveResolutionHeightFraction: 0.5,
    debugFreezeFrame: false,
    debugColorizeTiles: false,
    debugWireframe: false,
    debugShowBoundingVolume: false,
    debugShowContentBoundingVolume: false,
    debugShowViewerRequestVolume: false,
    debugShowGeometricError: false,
    debugShowRenderingStatistics: false,
    debugShowMemoryUsage: false,
    debugShowUrl: false,
}

/**
 * 默认显示区域
 */
export const getDefaultRectangle = (Cesium: Cesium) =>
    Cesium.Rectangle.fromDegrees(112.858933, 30.473384, 112.866068, 30.481188)

/**
 * 天地图影像底图
 */
export const buildBaseImageryProvider = (Cesium: Cesium) => {
    return new Cesium.UrlTemplateImageryProvider({
        url: tdtUrl + 'DataServer?T=img_w&x={x}&y={y}&l={z}&tk=' + token,
        subdomains: subdomains,
        tilingScheme: new Cesium.WebMercatorTilingScheme(),
        maximumLevel: 18,
    })
}

/**
 * 2D 建模图层
 */
export const buildTiffImageryProvider = (Cesium: Cesium) => {
    return new Cesium.UrlTemplateImageryProvider({
        url: `${host}:1234/api/tilesets/kshg-2d-image/{z}/{x}/{y}.jpg`,
        tilingScheme: new Cesium.WebMercatorTilingScheme(),
        minimumLevel: 10,
        maximumLevel: 24,
        tileWidth: 256,
        tileHeight: 256,
        rectangle: getDefaultRectangle(Cesium),
    })
}

/**
 * 添加 2D 建模图层
 * @param viewer Cesium.Viewer
 */
export const add2DImageLayer = (Cesium: Cesium, viewer: Cesium.Viewer) => {
    // 叠加 2D 影像底图
    viewer.imageryLayers.addImageryProvider(buildTiffImageryProvider(Cesium))
    // 切换到影像可视区域
    viewer.scene.camera.setView({ destination: getDefaultRectangle(Cesium) })
}

/**
 * 添加 3D 倾斜摄影模型
 * @param viewer Cesium.Viewer
 */
export const add3DTileset = (Cesium: Cesium, viewer: Cesium.Viewer) => {
    const tileset = new Cesium.Cesium3DTileset({
        url: `${host}:9003/model/ehXZf942/tileset.json`,
        ...defaultTilesetConfig,
        shadows: Cesium.ShadowMode.DISABLED,
    })

    tileset.readyPromise.then((tileset) => {
        // 模型与地面的高度差，单位：米
        // 20m 是通过手动调试出来的结果
        const height = -20
        const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)
        const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0)
        const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height)
        const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)

        // 叠加 3D 模型
        viewer.scene.primitives.add(tileset)
        // 切换到模型可视区域
        // viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.5, tileset.boundingSphere.radius * 1.0))
        // 切换到模型最佳可视区域
        viewer.camera.setView({
            destination: Cesium.Cartesian3.fromDegrees(112.86168, 30.48564, 350),
            orientation: {
                heading: Cesium.Math.toRadians(180),
                pitch: Cesium.Math.toRadians(-25),
                roll: 0,
            },
        })
    })
}

/**
 * 获取 Cesium Viewer 实例
 * @param ref 地图组件 ref
 * @returns Cesium.Viewer
 */
export const getMapViewerInstance = (ref: Ref<any>): Cesium.Viewer => toRaw(ref.value?.viewer) as Cesium.Viewer
