import { Subscriber } from 'cesium-extends'
import chroma from 'chroma-js'
import { parseWKT } from '@/utils/parseWKT'
import { difference } from 'lodash'
import { polygonGradient } from '@/js/polygonGradient'
import { polygonMaterial } from '@/js/polygon'
import { centerOfMass } from '@turf/turf'
import { useTree } from '@/utils/tree'

import { useHangjingPopup } from './hangjingPopup'

const { createPopup } = useHangjingPopup()
const { filterTreeNodeByField } = useTree()

export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
  let subscriber: Subscriber | null = null

  const colors = new Map()

  function addHangjingPolygon(ids, data) {
    subscriber = new Subscriber(viewer, {
      pickResult: {
        enable: true,
      },
    })

    // const ids = data.map(item => item.id)
    const addIds = difference(ids, [...polygonMap.keys()])
    const removeIds = difference([...polygonMap.keys()], ids)
    // 添加
    if (addIds.length > 0) {
      const nodes = filterTreeNodeByField({
        treeData: data.value,
        params: addIds,
        paramName: 'dataId',
      })
      nodes.forEach(({ data: hjData, dataId: id }) => {
        // const item = data.find(item => item.id === id)
        if (hjData) {
          if (hjData.zoneList.length > 0) {
            hjData.zoneList.forEach(zone => {
              addPolygon(zone, id)
            })
          } else {
            addPolygon(hjData)
          }
        }
      })
    }
    // 删除
    if (removeIds.length > 0) {
      console.log(removeIds, 'removeIds')
      removeIds.forEach(id => {
        removeEventSub(polygonMap.get(id))
        removeHangjingPolygon(id)
      })
    }
  }

  function addPolygon(item, parentId: number | null = null) {
    const { id, geom, title } = item
    const feature = parseWKT(geom)
    const position = feature.coordinates[0].map(pos => {
      return Cesium.Cartesian3.fromDegrees(...pos)
    })

    const labels = addTextAlongCurve('Cesium中文垂直排列测试', position)

    // console.log(item, id, position, 'id, position, color')
    // const randomColor =
    //   '#' + Math.random().toString(16).substring(2, 8).padEnd(6, '0')

    // if (!colors.has(id)) {
    //   const randomColor = chroma.random().alpha(0.5).hex()
    //   colors.set(id, randomColor)
    // }
    // if (zoneId) {
    //   if()
    // }

    const curId = parentId || id

    if (!colors.has(curId)) {
      const randomColor = chroma.random().brighten().alpha(0.6).hex()
      colors.set(curId, randomColor)
    }
    const color = colors.get(curId)

    const polygon = addPrimitivePolygon({
      id,
      color: color,
      position,
    })

    const centerPoint = centerOfMass(feature).geometry.coordinates

    const centerEntity = addPolygonCenter(centerPoint)
    addEventSub({
      parentId,
      id,
      entity: polygon,
      hjData: { ...item, centerPoint },
    })
    if (parentId) {
      if (polygonMap.get(parentId)) {
        polygonMap.get(parentId).push(polygon)
      } else {
        polygonMap.set(parentId, [polygon])
      }
      polygonMap.get(parentId).push(centerEntity)
    } else {
      polygonMap.set(id, polygon)
    }

    // console.log(polygonMap, 'polygonMap')
  }

  function addPolygonCenter(centerPoint: number[]) {
    return viewer.entities.add({
      show: false,
      position: Cesium.Cartesian3.fromDegrees(...centerPoint),
      point: {
        pixelSize: 10,
        color: Cesium.Color.RED,
      },
    })
  }

  function addPrimitivePolygon({
    id,
    position,
    color,
  }: {
    id: string
    position: Cesium.Cartesian3[]
    color: string
  }): Cesium.Primitive {
    // const polygonOptions = {
    //   extrudedHeight: 5000,
    //   polygonHierarchy: new Cesium.PolygonHierarchy(position),
    // }

    // const geometry = new Cesium.PolygonGeometry(polygonOptions)

    // const geometryInstance = new Cesium.GeometryInstance({
    //   geometry: geometry,
    //   id,
    // })

    // const primitive = new Cesium.Primitive({
    //   releaseGeometryInstances: false,
    //   asynchronous: false,
    //   geometryInstances: [geometryInstance],
    //   appearance: new Cesium.EllipsoidSurfaceAppearance({
    //     material: polygonGradient(color),
    //   }),
    // })
    // return viewer.scene.primitives.add(primitive)

    return viewer.entities.add({
      id,
      polyline: {
        positions: position,
        width: 1,
        material: Cesium.Color.RED,
      },
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(position),
        material: Cesium.Color.fromCssColorString(color),
        // material: polygonMaterial(color),
        // material: polygonGradient(color),
        // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      },
    })
  }
  function removeHangjingPolygon(id: string) {
    if (polygonMap.has(id)) {
      const polygon = polygonMap.get(id)
      if (polygon instanceof Array) {
        polygon.forEach(item => {
          // viewer.scene.primitives.remove(item)
          viewer.entities.remove(item)
        })
      } else {
        // viewer.scene.primitives.remove(polygonMap.get(id))
        viewer.entities.remove(polygonMap.get(id))
      }
      // viewer.entities.remove(hangjingMap.get(id))
      polygonMap.delete(id)
    }
  }

  function addEventSub({
    parentId,
    id,
    entity,
    hjData,
  }: {
    parentId: number | null
    id: number
    entity: Cesium.Entity
    hjData: Record<string, any>
  }) {
    subscriber &&
      subscriber.add(
        entity,
        (movement, entity) => {
          // console.log(movement, 'movement')
          // console.log(hjData, 'hjData')
          const position = Cesium.Cartesian3.fromDegrees(...hjData.centerPoint)
          ;(polygonMap.has(id) || polygonMap.has(parentId)) &&
            createPopup(id, { _value: position }, hjData)
        },
        'LEFT_CLICK'
      )
    // console.log(subscriber, '-------')
  }

  function removeEventSub(entity: Cesium.Entity) {
    subscriber && subscriber.remove(entity, 'LEFT_CLICK')
  }
  return {
    addHangjingPolygon,
    removeHangjingPolygon,
  }
}

function addTextAlongCurve(text, polygonPoints) {
  // 创建 Billboard 集合
  const billboardCollection = viewer.scene.primitives.add(
    new Cesium.BillboardCollection()
  )

  // 创建文字绘制的辅助函数
  function createTextTexture(text, angle) {
    const canvas = document.createElement('canvas')
    const context = canvas.getContext('2d')

    // 设置 Canvas 大小
    canvas.width = 20
    canvas.height = 20

    // 设置文字样式
    context.font = '20px sans-serif' // 支持中文
    context.fillStyle = 'blue'
    context.textAlign = 'center'
    context.textBaseline = 'middle'

    // 将文字绘制到 Canvas,并进行旋转
    context.clearRect(0, 0, canvas.width, canvas.height)
    context.save()

    // 旋转文字
    context.translate(canvas.width / 2, canvas.height / 2)
    context.rotate(angle)
    context.fillText(text, 0, 0)

    context.restore()

    return canvas
  }

  // 动态生成字符标注
  function generateLabels(cameraHeight) {
    billboardCollection.removeAll() // 清除之前的标注

    let charIndex = 0 // 当前字符索引
    for (let i = 0; i < polygonPoints.length - 1; i++) {
      const start = polygonPoints[i] // 当前边的起点
      const end = polygonPoints[i + 1] // 当前边的终点

      // 计算线段的方向向量
      const direction = Cesium.Cartesian3.subtract(
        end,
        start,
        new Cesium.Cartesian3()
      )
      Cesium.Cartesian3.normalize(direction, direction)

      // 计算垂直于线段的方向向量
      const perpendicular = Cesium.Cartesian3.cross(
        direction,
        Cesium.Cartesian3.UNIT_Z, // 使用 Z 轴(垂直地球表面)计算垂直方向
        new Cesium.Cartesian3()
      )
      Cesium.Cartesian3.normalize(perpendicular, perpendicular)

      // 计算线段的长度
      const length = Cesium.Cartesian3.distance(start, end)

      // 动态调整字符间隔,基于相机高度
      const baseSpacing = 50 // 基础字符间隔
      const charSpacing = Math.max((baseSpacing * cameraHeight) / 5000000, 30)

      // 按字符间隔放置文字
      let distance = 0
      while (distance < length && charIndex < text.length) {
        // 计算字符的位置
        const fraction = distance / length // 当前字符在边上的位置比例
        const position = Cesium.Cartesian3.lerp(
          start,
          end,
          fraction,
          new Cesium.Cartesian3()
        )

        // 计算旋转角度,使文字垂直于线段
        const angle = Math.atan2(perpendicular.y, perpendicular.x)

        // 创建带旋转的文字纹理
        const canvas = createTextTexture(text[charIndex], angle)

        // 添加 Billboard 显示文字
        billboardCollection.add({
          position: position,
          image: canvas, // 使用生成的文字纹理
          // pixelOffset: new Cesium.Cartesian2(10, 0),
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        })

        // 更新字符索引和距离
        charIndex++
        console.log(charSpacing)
        distance += charSpacing * 2000
        // distance *= 2
        console.log(distance)
      }

      // 如果字符已用完,跳出循环
      if (charIndex >= text.length) {
        break
      }
    }
  }

  // 初始化标注(根据初始相机高度)
  generateLabels(viewer.camera.positionCartographic.height)

  // 监听相机变化事件,动态更新字符间隔
  viewer.camera.changed.addEventListener(() => {
    const cameraHeight = viewer.camera.positionCartographic.height
    generateLabels(cameraHeight)
  })
}