<template>
  <div class="project-layer-wrapper height-100">
    <div class="scrollbar">
      <LayersTree :layer-data="mapLayers" class="project-layer-content" @select="selectLayer"
        v-model:selectedKeys="selectedKeys" v-model:checkedKeys="checkedKeys" v-model:expandedKeys="expandedKeys" />
    </div>
    <a-drawer title="地图元素" placement="right" :closable="true" v-model:visible="visible" :mask="true"
      getContainer="#g-container" :wrap-style="{ position: 'absolute' }" wrapClassName="drawer-element-wrapper"
      @close="closeDrawer" width="300">
      <div class="drawer-element-content">
        <div class="element-item">
          <span class="mr30">名称:</span>
          <a-input v-model:value="layerState.layerName" style="width:110px" placeholder="element name"
            @change="changeLayer" />
        </div>
        <div class="element-item" v-if="layerState.currentType === geoType.Point">
          <span class="mr30">经度:</span>
          {{ layerState.longitude || '--' }}
        </div>
        <div class="element-item" v-if="layerState.currentType === geoType.Point">
          <span class="mr30">纬度:</span>
          {{ layerState.latitude || '--' }}
        </div>
        <div class="element-item" v-if="layerState.element_from === 2">
          <span class="mr30">高度:</span>
          {{ layerState.height || '--' }}
        </div>
        <div class="element-item" v-if="layerState.currentType === geoType.Polygon">
          <span class="mr30">面积:</span>
          {{ layerState.area || '--' }}
        </div>
        <div class="color-content">
          <span class="mr30">颜色: </span>
          <div v-for="item in colors" :key="item.id" class="color-item" :style="'background:' + item.color"
            @click="changeColor(item)">
            <svg-icon v-if="item.color === layerState.color" :size="18" name="check"></svg-icon>
          </div>
        </div>
        <div class="element-item">
          <span class="mr30">用户:</span>
          {{ layerState.user_name || '--' }}
        </div>
        <div class="element-item">
          <span class="mr30">来源:</span>
          <Icon v-if="layerState.element_from === 2">
            <template #component>
              <svg width="1em" height="1em" fill="currentColor" viewBox="0 0 1024 1024">
                <path
                  d="M1024 418.21v576H0v-576h1024z m-672 192c-53.02 0-96 42.98-96 96s42.98 96 96 96 96-42.98 96-96-42.98-96-96-96z m320 0c-53.02 0-96 42.98-96 96s42.98 96 96 96 96-42.98 96-96-42.98-96-96-96zM236.59 29.79h125.55v320H236.59v-320z m425.28 0h125.55v320H661.87v-320z"
                  p-id="4408" />
              </svg>
            </template>
          </Icon>
          <DesktopOutlined v-else />
        </div>
      </div>
      <div class="flex-row flex-justify-around flex-align-center mt20">
        <a-button type="primary" @click="deleteElement">删除</a-button>
      </div>
    </a-drawer>
    <PhotoDrawer :visible="state.photoDrawerVisible" :fileId="selectedKeys[0]" :closeDrawer="closeDrawer" />
  </div>
</template>

<script lang="ts" setup>
import { onMounted, reactive, ref, watch } from 'vue'
import Icon from '@ant-design/icons-vue';
import { DesktopOutlined } from '@ant-design/icons-vue';
import LayersTree from '/@/components/LayersTree.vue'
import PhotoDrawer from './components/PhotoDrawer.vue'
import { MapElementEnum } from '/@/constants/map'
import { useGMapCover } from '/@/hooks/use-g-map-cover'
import { GeojsonCoordinate, LayerResource } from '/@/types/map'
import { Color, GeoType } from '/@/types/mapLayer'
import {
  deleteElementReq,
  getElementGroupsReq,
  updateElementsReq
} from '/@/api/layer'
import { useMyStore } from '/@/store'
import { gcj02towgs84, wgs84togcj02 } from '/@/vendors/coordtransform'
import { getRoot } from '/@/root'

const root = getRoot()

interface Props {
  mapClickElement: {
    id: string,
    type: string,
  },
};

const props = withDefaults(defineProps<Props>(), {

});

const state = reactive({
  photoDrawerVisible: false,
})

watch(() => props.mapClickElement, (newValue, oldValue) => {
  if (newValue.id) {
    if (newValue.type === 'DEFAULT') {// 默认文件夹
      // 默认文件夹列表
      const defaultFileList: any = mapLayers.value.filter((item: any) => item.type === 2);
      if (defaultFileList.length === 0) {
        return;
      }
      const pid = defaultFileList[0].id;
      expandedKeys.value = [pid];
      selectedKeys.value = [`resource__${newValue.id}`];
      selectedLayer.value = getCurrentLayer(`resource__${newValue.id}`)
      setBaseInfo()
      visible.value = true;
      state.photoDrawerVisible = false
    } else if (newValue.type === 'PHOTO') {
      const expandedKeyList: string[] = [];
      // 图片标注列表
      const photoList: any = mapLayers.value.filter((item: any) => item.type === 3);
      if (photoList.length === 0) {
        return;
      }
      const list = photoList[0];
      expandedKeyList.push(list.id);
      list.elements.forEach((item: any) => {
        item.elements.forEach((element: any) => {
          if (element.id === newValue.id) {
            const coordinates = element.resource.content.geometry.coordinates;
            root.$map.setCenter(coordinates);
            expandedKeyList.push(element.pid)
            expandedKeys.value = expandedKeyList;
            selectedKeys.value = [`resource__${newValue.id}`];
            selectedLayer.value = getCurrentLayer(`resource__${newValue.id}`)
            state.photoDrawerVisible = true
            visible.value = false;
          }
        });
      })
    }
  }
}, { deep: true });

const store = useMyStore()
let useGMapCoverHook = useGMapCover()
const mapLayers = ref(store.state.Layers)
const checkedKeys = ref<string[]>([])
const expandedKeys = ref<string[]>([])
const selectedKeys = ref<string[]>([])
const selectedKey = ref<string>('')
const selectedLayer = ref<any>(null)
const visible = ref<boolean>(false)
const geoType = GeoType

const layerState = reactive({
  layerId: '',
  layerName: '',
  longitude: 0,
  latitude: 0,
  height: 0,
  area: '',// 面积
  currentType: '',// “LineString”,"Polygon","Point"
  color: '#212121',
  user_name: '',
  element_from: 1,// 1-web 2-遥控器
})

const colors = ref<Color[]>([
  { id: 1, name: 'BLUE', color: '#2D8CF0', selected: true },
  { id: 2, name: 'GREEN', color: '#19BE6B', selected: false },
  { id: 3, name: 'YELLOW', color: '#FFBB00', selected: false },
  { id: 4, name: 'ORANGE', color: '#B620E0', selected: false },
  { id: 5, name: 'RED', color: '#E23C39', selected: false },
  { id: 6, name: 'NAME_DEFAULT', color: '#212121', selected: false }
])

const scorllHeight = ref()

async function getAllElement() {
  getElementGroups('init')
  setTimeout(() => {
    useGMapCoverHook = useGMapCover()
    initMapCover()
  }, 1000)
}

function initMapCover() {
  mapLayers.value.forEach((item: any) => {
    if (item.elements) {
      setMapCoverByElement(item.elements)
    }
  })
}

watch(() => store.state.Layers, newData => {
  mapLayers.value = newData
}, { deep: true })

function setMapCoverByElement(elements: LayerResource[]) {
  elements.forEach((element: any) => {
    if (element.elements && element.elements.length) {// 图片标注
      element.elements.forEach((item: any) => {
        const name = item.name;
        const content: any = item.resource?.content;
        const pictureInfo = content.picture;
        const coordinates: any = content.geometry.coordinates;
        useGMapCoverHook.updatePhotoElement(pictureInfo.file_id, name, pictureInfo.thumbnail_url, coordinates);
      })
    } else {// 默认文件夹
      const name = element.name;
      const content: any = element.resource?.content;
      const color = content.properties.color;
      updateMapElement(element, name, color);
    }
  })
}

function updateMapElement(
  element: LayerResource,
  name: string,
  color: string | undefined
) {
  const geoType = element.resource?.content.geometry.type
  const id = element.id
  const type = element.resource?.type as number
  if (MapElementEnum.PIN === type) {
    const coordinates = element.resource?.content.geometry
      .coordinates as GeojsonCoordinate
    useGMapCoverHook.updatePinElement(id, name, coordinates, color)
  } else if (MapElementEnum.LINE === type && geoType === 'LineString') {
    const coordinates = element.resource?.content.geometry
      .coordinates as GeojsonCoordinate[]
    useGMapCoverHook.updatePolylineElement(id, name, coordinates, color)
  } else if (MapElementEnum.POLY === type && geoType === 'Polygon') {
    const coordinates = element.resource?.content.geometry
      .coordinates as GeojsonCoordinate[][]
    useGMapCoverHook.updatePolygonElement(id, name, coordinates, color)
  }
}

function selectLayer(keys: string[], e) {
  visible.value = false
  state.photoDrawerVisible = false
  if (e.selected) {
    selectedKey.value = e.node.eventKey
    selectedLayer.value = getCurrentLayer(selectedKey.value)
    const type = e.node.label;
    if (type === 'DEFAULT') {// 默认文件夹
      setBaseInfo()
      visible.value = true;
    } else if (type === 'PHOTO') {// 图片标注
      state.photoDrawerVisible = true;
    }
  }
}

function getCurrentLayer(id: string) {
  const Layers = store.state.Layers
  const key = id.replaceAll('resource__', '')
  let layer = null
  const findCan = function (V: any) {
    V.forEach((item: any) => {
      if (item.id === key) {
        layer = item
      }
      if (item.elements) {
        findCan(item.elements)
      }
    })
  }
  findCan(Layers)
  return layer
}

function setBaseInfo() {
  const layer = selectedLayer.value
  if (layer) {
    const content = layer.resource?.content;
    const coordinates = content.geometry.coordinates;
    const type = content.geometry.type;
    layerState.layerId = layer.id;
    layerState.layerName = layer.name;
    layerState.longitude = coordinates[0];
    layerState.latitude = coordinates[1];
    layerState.height = layer.height;
    layerState.currentType = type;
    layerState.color = content.properties.color;
    layerState.user_name = layer.resource?.user_name;
    layerState.element_from = layer.element_from;
    if (type === 'Polygon') {
      const area = useGMapCoverHook.getPolygonArea(coordinates);
      layerState.area = area + 'm²';
    }
  }
}

onMounted(() => {
  const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement
  const parent = element?.parentNode as HTMLDivElement
  scorllHeight.value = parent?.clientHeight - parent.firstElementChild!.clientHeight
  getAllElement()
})

function closeDrawer() {
  store.commit('SET_MAP_CLICK_ELEMENT', {
    id: '',
    type: '',
  });
  visible.value = false
  state.photoDrawerVisible = false
  selectedKeys.value = []
}

function changeColor(color: Color) {
  layerState.color = color.color
  updateElements()
}

function changeLayer(val: string) {
  updateElements()
}

async function deleteElement() {
  const elementid = selectedLayer.value.id

  await deleteElementReq(elementid, {}).then(async (res: any) => {
    if (res.code !== 0) {
      return
    }
    visible.value = false
    // 移除标点
    useGMapCoverHook.removeCoverFromMap(elementid)
    // 移除文本覆盖物
    useGMapCoverHook.removeCoverFromMap(elementid + '_other')
    getElementGroups()
  })
}

async function getElementGroups(type?: string) {
  const result = await getElementGroupsReq({
    groupId: '',
    isDistributed: true
  })
  mapLayers.value = result.data.map((item: any) => {
    const data = { ...item };
    if (item.elements) {// 默认文件夹
      data.elements = item.elements.map((o: any) => {
        return {
          ...o,
          id: o.id,
          height: o.resource.content.geometry.coordinates[2]
        }
      })
    } else {// 图片标注
      data.elements = item.child_groups.map((o: any) => {
        return {
          ...o,
          elements: o.elements.map((val: any) => {
            const values = { ...val };
            const coordinates = values.resource?.content.geometry.coordinates as GeojsonCoordinate;
            const transResult = wgs84togcj02(
              coordinates[0],
              coordinates[1]
            ) as GeojsonCoordinate
            values.id = val.resource.content.picture.file_id;
            values.pid = 'resource__' + o.id;
            values.resource.content.geometry.coordinates = transResult;
            return values;
          })
        }
      });
      delete data.child_groups;
    }
    return data;
  })
  mapLayers.value = updateWgs84togcj02()
  if (type && type === 'init') {
    store.dispatch('setLayerInfo', mapLayers.value)
  }
  store.commit('SET_LAYER_INFO', mapLayers.value)
}

async function updateElements() {
  let content = null
  const currentLayer = selectedLayer.value
  content = currentLayer.resource.content
  content.properties.color = layerState.color
  // 移除标点
  useGMapCoverHook.removeCoverFromMap(currentLayer.id)
  // 移除文本覆盖物
  useGMapCoverHook.removeCoverFromMap(currentLayer.id + '_other')
  updateMapElement(selectedLayer.value, layerState.layerName, layerState.color)
  const result = await updateElementsReq(layerState.layerId, {
    name: layerState.layerName,
    content: content
  })
  getElementGroups()
}

function updateWgs84togcj02() {
  const layers = mapLayers.value
  layers.forEach((item: any) => {
    if (item.elements) {
      item.elements.forEach((ele: any) => {
        updateCoordinates('wgs84-gcj02', ele)
      })
    }
  })
  return layers
}

function updateCoordinates(transformType: string, element: LayerResource) {
  const type = element.resource?.type as number
  if (element.resource) {
    if (MapElementEnum.PIN === type) {
      const coordinates = element.resource?.content.geometry
        .coordinates as GeojsonCoordinate
      if (transformType === 'wgs84-gcj02') {
        const transResult = wgs84togcj02(
          coordinates[0],
          coordinates[1]
        ) as GeojsonCoordinate
        element.resource.content.geometry.coordinates = transResult
      } else if (transformType === 'gcj02-wgs84') {
        const transResult = gcj02towgs84(
          coordinates[0],
          coordinates[1]
        ) as GeojsonCoordinate
        element.resource.content.geometry.coordinates = transResult
      }
    } else if (MapElementEnum.LINE === type) {
      const coordinates = element.resource?.content.geometry
        .coordinates as GeojsonCoordinate[]
      if (transformType === 'wgs84-gcj02') {
        coordinates.forEach((coordinate, i, arr) => {
          arr[i] = wgs84togcj02(
            coordinate[0],
            coordinate[1]
          ) as GeojsonCoordinate
        })
      } else if (transformType === 'gcj02-wgs84') {
        coordinates.forEach((coordinate, i, arr) => {
          arr[i] = gcj02towgs84(
            coordinate[0],
            coordinate[1]
          ) as GeojsonCoordinate
        })
      }
      element.resource.content.geometry.coordinates = coordinates
    } else if (MapElementEnum.POLY === type) {
      const coordinates = element.resource?.content.geometry
        .coordinates[0] as GeojsonCoordinate[]
      if (transformType === 'wgs84-gcj02') {
        coordinates.forEach((coordinate, i, arr) => {
          arr[i] = wgs84togcj02(
            coordinate[0],
            coordinate[1]
          ) as GeojsonCoordinate
        })
      } else if (transformType === 'gcj02-wgs84') {
        coordinates.forEach((coordinate, i, arr) => {
          arr[i] = gcj02towgs84(
            coordinate[0],
            coordinate[1]
          ) as GeojsonCoordinate
        })
      }
      element.resource.content.geometry.coordinates = [coordinates]
    }
  }
}
</script>

<style lang="scss" scoped>
@import '/@/styles/index.scss';
</style>
<style lang="scss">
.drawer-element-wrapper {
  .ant-drawer-content {
    background-color: $dark-highlight;
    color: $text-white-basic;

    .ant-drawer-header {
      background-color: $dark-highlight;

      .ant-drawer-title {
        color: $text-white-basic;
      }

      .ant-drawer-close {
        color: $text-white-basic;
      }
    }

    .ant-input {
      background-color: #101010;
      border-color: $dark-border;
      color: $text-white-basic;
    }
  }

  .color-content {
    display: flex;
    align-items: center;
    margin: 8px 0 10px;

    .color-item {
      cursor: pointer;
      width: 18px;
      height: 18px;
      line-height: 18px;
      display: flex;
      align-items: center;
      margin-right: 5px;
    }
  }

  .title {
    display: inline-flex;
    width: 80px;
  }

  .element-item {
    margin-bottom: 10px;
  }
}

.scrollbar {
  overflow: auto;
}
</style>