<template>
  <div class="mapBox">
    <div
      id="map"
      @dragover="e => e.preventDefault()"
      @dragleave="isCheck = false"
      @dragenter="isCheck = true"
    />
    <div
      v-if="isEdit"
      class="mapBox-menu"
    >
      <n-tree-select
        v-model:value="selected"
        :options="options"
        label-field="name"
        key-field="uuid"
        children-field="childList"
        check-strategy="child"
        placeholder="请选择车站"
        @update:value="changeMap"
      />
      <div class="mapBox-menu-content">
        <n-scrollbar>
          <template
            v-for="(item, index) in iconList"
            :key="index"
          >
            <div
              class="mapBox-menu-content-item"
              draggable="true"
              @dragstart="currentItem = item"
              @dragend="itemDragEnd"
            >
              <img
                :src="item.icon"
                alt=""
                srcset=""
                draggable="false"
              >
              <p>
                {{ item.name }}
              </p>
            </div>
          </template>
        </n-scrollbar>
      </div>
    </div>
    <div
      v-if="isEdit && showPoup"
      class="mapBox-poup"
    >
      <n-form
        ref="formRef"
        :model="formMode"
        label-placement="left"
        label-width="auto"
        size="small"
        :rules="rules"
      >
        <n-form-item
          label="元素编号"
          path="uuid"
        >
          <n-input
            v-model:value="formMode.uuid"
            disabled
          />
        </n-form-item>
        <n-form-item
          label="资产编号"
          path="guid"
        >
          <n-select
            v-model:value="formMode.guid"
            placeholder="请选择"
            label-field="name"
            value-field="guid"
            :options="assetOption"
            @update:value="selectChange"
          />
        </n-form-item>
        <n-form-item
          label="元素类型"
          path="type"
        >
          <n-input
            v-model:value="formMode.type"
            disabled
          />
        </n-form-item>
        <n-form-item
          label="x 坐 标 "
          path="x"
        >
          <n-input-number
            v-model:value="formMode.x"
            clearable
            :show-button="false"
            @blur="resetMarker('lng', formMode.x)"
          />
        </n-form-item>
        <n-form-item
          label="y 坐 标 "
          path="y"
        >
          <n-input-number
            v-model:value="formMode.y"
            clearable
            :show-button="false"
            @blur="resetMarker('lat', formMode.y)"
          />
        </n-form-item>
        <n-form-item
          label="横向缩放"
          path="scaleX"
        >
          <n-input-number
            v-model:value="formMode.scaleX"
            clearable
            :min="0.1"
            :show-button="false"
            @blur="resetMarker('scaleX', formMode.scaleX, '0')"
          />
        </n-form-item>
        <n-form-item
          label="纵向缩放"
          path="scaleY"
        >
          <n-input-number
            v-model:value="formMode.scaleY"
            clearable
            :min="0.1"
            :show-button="false"
            @blur="resetMarker('scaleY', formMode.scaleY, '1')"
          />
        </n-form-item>
        <n-form-item
          label="水平翻转"
          path="flipX"
        >
          <n-switch
            v-model:value="formMode.flipX"
            @update:value="resetMarker('flipX', formMode.flipX)"
          />
        </n-form-item>
        <n-form-item
          label="垂直翻转"
          path="flipY"
        >
          <n-switch
            v-model:value="formMode.flipY"
            @update:value="resetMarker('flipY', formMode.flipY)"
          />
        </n-form-item>
      </n-form>
      <div class="mapBox-poup-btns">
        <n-button
          type="error"
          ghost
          @click="del"
        >
          删除
        </n-button>
        <n-button
          type="primary"
          @click="save"
        >
          保存
        </n-button>
      </div>
    </div>
  </div>
</template>

<script setup lang='ts'>
import * as L from 'leaflet'
import {
  onMounted,
  onUnmounted,
  Ref, ref, watch
} from 'vue'
import '@/../node_modules/leaflet/dist/leaflet.css'
import { LatLngExpression } from 'leaflet';
// ----- 修复L 增加tooltip 缩放报错 重要！！

(L.Tooltip as any).prototype._animateZoom = function (e: { zoom: any; center: any; }) {
  if (!(this as any)._map) {
    return
  }
  const pos = (this as any)._map._latLngToNewLayerPoint((this as any)._latlng, e.zoom, e.center) as any
  (this as any)._setPosition(pos)
};

(L.Tooltip as any).prototype._updatePosition = function () {
  if (!(this as any)._map) {
    return
  }
  const pos = (this as any)._map.latLngToLayerPoint((this as any)._latlng) as any
  (this as any)._setPosition(pos)
}
// ---------

export interface Item {
  icon: string,
  x?: number,
  y?: number,
  scaleX?: number,
  scaleY?: number,
  guid?: string,
  type?: string,
  uuid?: string,
  item?: string,
  isAdd?: boolean,
  deviceId?: string,
  itemName?: string
}

export interface BaseMap {
  width: number,
  height: number,
  mapId: string,
  name?: string
  imgUrl: string,
  trackType?: number, // 1电扶梯 2给排水 3通风 4照明 5车站环境检测 6车站暖通 7车站动环
  showTip?: boolean,
  uuid?: string
}

const props = withDefaults(defineProps<{
  isEdit?: boolean, // 是否编辑
  baseMap?: BaseMap
}>(), {
  isEdit: true,
  baseMap: () => ({
    imgUrl: '/system/track/djy.png', width: 1400, height: 430, mapId: 'd33d83d7-02cb-2ce3-37e1-e563320b93dd', showTip: false
  })
})
const emit = defineEmits<{(evt: 'markerClick', value: Item): void }>()
const Map = ref()
const iconList = ref([
  { name: '电扶梯', icon: 'https://gsm.jdjinsui.com/gsmImage/system/track/电扶梯正常.png' }
] as { icon: string, name: string }[])
const currentItem: Ref<Item | undefined> = ref()
const isCheck = ref(false)
const options = ref([
  {
    imgUrl: '/system/track/djy.png', width: 1400, height: 430, mapId: 'd33d83d7-02cb-2ce3-37e1-e563320b93dd', name: 'test', uuid: 'e5cdf830-587a-11ef-a53a-f3fe72299e7d'
  }
] as BaseMap[])
const selected = ref('')
const assetOption = ref([])
const formRef = ref()
const formMode = ref({
  uuid: '',
  guid: '',
  type: '',
  x: 0,
  y: 0,
  scaleX: 1,
  scaleY: 1,
  flipX: false,
  flipY: false,
  icon: '',
  tip: '',
  isAdd: false
})
const rules = { guid: { required: true, message: '请选择资产' } }
const showPoup = ref(false)
const currentMap: Ref<BaseMap | undefined> = ref()
const currentMarker = ref()
const allMarker = ref([] as L.Marker[])

// 资产下拉
function selectChange(_: string, option: Item) {
  formMode.value.type = option.type || ''
}

// 重置marker样式
function resetMarker(type: string, num: number | boolean, id?: string) {
  if (type === 'lat' || type === 'lng') {
    const obj = currentMarker.value.getLatLng()
    obj[type] = num
    currentMarker.value.setLatLng(obj)
    console.log('位置更新', obj)
  } else {
    const newIcon = currentMarker.value.getIcon()
    if (type === 'scaleX' || type === 'scaleY') {
      newIcon.options.iconSize[id!] = newIcon.options.iconSize[id!] * (num as number)
    } else {
      const newHtml = newIcon.options.html.replace(/style="[^=>]*"/g, (s: string) => {
        const a = s.split(' ')
        const c = type === 'flipY' ? 'rotateX' : 'rotateY'
        const n = type === 'flipY' ? 1 : 2
        a[n] = num ? `${c}(180deg)${n === 2 ? ';"' : ''}` : `${c}(0deg)${n === 2 ? ';"' : ''}`
        const b = a.join(' ')
        return b
      })
      newIcon.options.html = newHtml
    }
    currentMarker.value.setIcon(newIcon)
  }
}

// marker选中状态
function selectMaker(marker: L.Marker) {
  for (let k = 0; k < allMarker.value.length; k++) {
    const el = allMarker.value[k]
    const dom = el.getElement()
    if ((el as Any)._leaflet_id === (marker as Any)._leaflet_id) {
      dom!.style.boxShadow = '0 0 4px 2px #ff891a'
    } else {
      dom!.style.boxShadow = 'none'
    }
  }
  currentMarker.value = marker
}

// 查询设备列表+设置poup
function setPoupData(marker: L.Marker, option: Item) {
  // 查询设备列表
  // socketService.send('item.query', { itemtype: option.deviceId, isPaging: 0, region: selected.value }).then((res) => {
  //   const { success, data: { list } } = res
  //   if (success && list) {
  //     assetOption.value = list
  //   }
  // })
  formMode.value.uuid = option.uuid || ''
  formMode.value.guid = option.guid || option.item || ''
  formMode.value.type = option.type || ''
  formMode.value.x = option.x || 0
  formMode.value.y = option.y || 0
  formMode.value.isAdd = option.isAdd || false
  // 移除其它选中状态
  selectMaker(marker)
  showPoup.value = true
}

// 添加marker
function addMarker(option: Item) {
  if (!Map.value) throw 'Map 未初始化'
  if (!option.icon) return console.log('缺少参数')

  // 自定义图标
  const img = `<img src="${option.icon}" style="width:100%;height:100%;transform: rotateX(0deg) rotateY(0deg);"/>`
  const ICON = L.divIcon({
    iconSize: [ (option.scaleX || 1) * 30, (option.scaleY || 1) * 30 ],
    html: img
  })
  const marker = L.marker([ option.y || 0, option.x || 0 ], {
    icon: ICON,
    draggable: props.isEdit, // 是否可通过鼠标/触摸拖动。
    riseOnHover: true
  }).addTo(Map.value)
  // add
  allMarker.value.push(marker)
  // 显示tip
  if (props.baseMap.showTip && option.itemName) marker.bindTooltip(option.itemName, { direction: 'top', className: 'resetTips' })
  // 显示poup
  if (isCheck.value) {
    console.log('添加marker', option)
    setPoupData(marker, option)
  }
  // 事件
  marker.addEventListener('click', () => {
    console.log('marker点击', option)
    setPoupData(marker, option)
    emit('markerClick', option)
  })
  marker.addEventListener('dragend', (e) => {
    console.log('marker拖动', option)
    const { lat, lng } = e.target.getLatLng()
    option.x = lng
    option.y = lat
    setPoupData(marker, option)
  })
}

// 拖拽=>添加marker
function itemDragEnd(e: DragEvent) {
  e.preventDefault()
  const point = Map.value.containerPointToLayerPoint([ e.layerX, e.layerY ]) // 给定相对于origin pixel的相应像素坐标
  const lnglat = Map.value.layerPointToLatLng(point) // 给定地理坐标，转换为相对于origin pixel的相应像素坐标
  if (isCheck.value) {
    addMarker({
      ...currentItem.value, x: lnglat.lng, y: lnglat.lat, isAdd: true
    } as Item)
  }
  isCheck.value = false
}

// 查询marker+绑定
async function bindMarker(mapId: string) {
  if (!mapId) return
  // 清除
  if (allMarker.value.length) {
    for (let k = 0; k < allMarker.value.length; k++) {
      const marker = allMarker.value[k]
      marker.remove()
    }
    allMarker.value = []
  }
  // 添加所有
  // let page = 1
  // let pages = 0
  // do {
  //   const obj = {
  //     map: mapId,
  //     pageSize: 100,
  //     isPaging: 0,
  //     page: page++
  //   } as { trackType?: number }
  //   if (props.baseMap.trackType) obj.trackType = props.baseMap.trackType
  //   const { data } = await socketService.send('monitor.itemQuery', obj)
  //   store.setObtainedDevices(data.list)
  //   console.log('底图关联的marker', data.list)
  //   if (data.list) {
  //     for (let k = 0; k < data.list.length; k++) {
  //       const el = data.list[k]
  //       const obj = {
  //         parent: el,
  //         ...el.mapElement,
  //         icon: import.meta.env.VITE_IMG_URL + el.icon,
  //         showTip: props.baseMap.showTip
  //       }
  //       addMarker(obj)
  //     }
  //   }
  //   pages = data.pages
  // } while (page <= pages)
}

// 自定义marker
function drawMarker(item: { latLng: number[], icon: string, children: any, label: string }) {
  if (!Map.value) return console.log('Map未初始化')
  if (!item.latLng || !item.latLng.length) return console.log('缺少参数')
  // 自定义图标
  const img = `<div class="newMark" style="background-image:url(${item.icon})">${item.label}</div>`
  const ICON = L.divIcon({
    iconSize: [ 100, 28 ],
    html: img,
    iconAnchor: [ -5, 14 ]
  })
  const marker = L.marker(item.latLng as LatLngExpression, {
    title: item.children[0],
    icon: ICON,
    draggable: false,
    riseOnHover: true // 该标记将位于其他标记的顶部
  })
  marker.addTo(Map.value)
  marker.addEventListener('click', (event) => {
    console.log('marker点击', event)
    // const { options: { title } } = event.target
    // const path = userData.getUserData().permission.find((el: { url: string }) => el.url === '/objHome')
    // if (path) {
    //   // store.setCurrentTunnel({ ...title })
    //   // store.setCurrentUuid(null)
    //   localStorage.setItem('currentTunnel', JSON.stringify({ ...title }))
    //   // router.push('/objHome')
    // } else {
    //   window.$notification.warning({ title: '你没有权限，请联系管理员！', duration: 2000 })
    // }
  })
  return marker
}

// 切换底图
async function changeMap(_: string, option: BaseMap) {
  console.log('切换底图', option)
  if (!Map.value) return
  // 清除layer
  Map.value.eachLayer((layer: L.Layer) => {
    Map.value.removeLayer(layer)
  })
  // 添加底图
  if (!option.imgUrl || !option.width || !option.height || !option.mapId) return window.$notification.error({ content: '底图缺少相关参数', duration: 3000, keepAliveOnHover: true })
  currentMap.value = option
  L.imageOverlay(`https://gsm.jdjinsui.com/gsmImage${option.imgUrl}`, [ [ 0, 0 ], [ option.height, option.width ] ]).addTo(Map.value)
  Map.value.setView([ option.height / 2, option.width / (props.isEdit ? 3.5 : 2) ], 0)
  // 获取底图绑定的maker
  bindMarker(option.mapId)
}

// 初始化底图
function initMap(option: BaseMap) {
  if (!option) return
  Map.value = L.map('map', {
    zoom: 0,
    maxZoom: 1,
    minZoom: 0,
    zoomSnap: 0.1,
    center: [ option.height / 2, option.width / (props.isEdit ? 3.5 : 2) ],
    crs: L.CRS.Simple,
    attributionControl: false,
    zoomControl: false
  }).addEventListener('click', (e) => {
    console.log('map点击', e)
    if (currentMarker.value) currentMarker.value.getElement().style.boxShadow = 'none'
    formMode.value.flipX = false
    formMode.value.flipY = false
    formMode.value.scaleX = 1
    formMode.value.scaleY = 1
    formMode.value.uuid = ''
    showPoup.value = false
  })

  // 获取底图列表
  // socketService.send('region.map').then((res) => {
  //   const { success, data } = res
  //   if (success && data.length) {
  //     options.value = data.map((el: { childList: Any[]; }) => {
  //       if (el.childList) {
  //         el.childList.forEach((es) => {
  //           if (es.mapId === props.baseMap.mapId) selected.value = es.id
  //           try {
  //             const { width, height, imgUrl } = JSON.parse(es.mapConfig)
  //             es.width = width
  //             es.height = height
  //             es.imgUrl = imgUrl
  //           } catch (error) {
  //             console.log('底图配置数据格式错误')
  //           }
  //         })
  //       }
  //       return el
  //     })
  //   }
  // })

  // 获取所有maker类型
  // socketService.send('itemType.search', { belongs: '3' }).then((res) => {
  //   const { success, data } = res
  //   if (success && data.length) iconList.value = data.map((el: { imageUrl: string; name: string; guid: string }) => ({ icon: import.meta.env.VITE_IMG_URL + el.imageUrl, name: el.name, deviceId: el.guid }))
  // })

  if (props.isEdit) { window.$notification.warning({ content: '请选择车站', duration: 3000, keepAliveOnHover: true }) } else {
    changeMap('', option)
  }
}

// 保存->更新marker
async function save() {
  await formRef.value.validate()
  const mapElementList = [ {
    flipX: formMode.value.flipX,
    flipY: formMode.value.flipY,
    item: formMode.value.guid,
    map: currentMap.value!.mapId,
    scaleX: formMode.value.scaleX,
    scaleY: formMode.value.scaleY,
    type: formMode.value.type,
    uuid: formMode.value.uuid,
    visiable: true,
    x: formMode.value.x,
    y: formMode.value.y
  } ]
  console.log('保存', mapElementList, formMode.value.isAdd)
  // const url = formMode.value.isAdd ? 'mapElement.insert' : 'mapElement.update'
  // const { success } = await socketService.send(url, { mapElementList })
  // if (success) {
  //   bindMarker(currentMap.value!.mapId)
  //   window.$notification.success({ content: formMode.value.isAdd ? '添加成功' : '修改成功', duration: 2000 })
  //   showPoup.value = false
  // }
}

// 删除当前
async function del() {
  if (!currentMarker.value) return
  const fdid = allMarker.value.findIndex((el: Any) => el._leaflet_id === currentMarker.value._leaflet_id)
  if (fdid !== -1) {
    if (!formMode.value.isAdd) {
      // const { success } = await socketService.send('mapElement.delete', [ formMode.value.uuid ])
      // if (success) window.$notification.success({ content: '删除成功', duration: 2000 })
    }
    allMarker.value.splice(fdid, 1)
    currentMarker.value.remove()
    showPoup.value = false
  } else {
    throw '删除失败！'
  }
}

// 销毁
function destory() {
  if (!Map.value) return
  console.log('销毁')
  Map.value.eachLayer((layer: L.Layer) => {
    Map.value.removeLayer(layer)
  })
  allMarker.value = []
  currentMarker.value = undefined
  currentMap.value = undefined
  Map.value = null
}

onMounted(() => {
  document.title = 'leaflet画图'
  initMap(props.baseMap)
})

watch(() => props.baseMap, (v) => {
  if (Map.value) {
    changeMap('', v)
  } else {
    initMap(v)
  }
}, { deep: true })

onUnmounted(() => destory())
</script>
<style lang="scss" scoped>
.mapBox {
  width: 100vw;
  height: 100vh;
  background: none;
  position: relative;

  #map {
    width: 100%;
    height: 100%;
    background: #011719;

    :deep(.leaflet-div-icon) {
      background: none;
      border: none;
      border-radius: 6px;
    }

    :deep(.resetTips) {
      height: 33px;
      background: #06353A;
      border: 1px solid #34C0AE;
      color: white;

      &::before {
        border-top-color: #34C0AE;
      }

      p {
        margin: 0;
        font-size: 14px;
      }
    }
  }

  &-menu {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 601;
    background: white;
    width: 380px;
    height: 100%;
    padding: 10px;

    &-content {
      width: 100%;
      height: calc(100% - 44px);

      :deep(.n-scrollbar-content) {
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
      }

      &-item {
        text-align: center;
        width: 78px;
        height: 78px;
        padding: 10px 0;
        border: 1px solid #C9D3DD;
        cursor: grab;
        margin-top: 16px;

        &:not(:nth-child(4n)) {
          margin-right: 16px;
        }

        img {
          width: 50px;
          height: 40px;
        }

        p {
          margin: 0;
          color: #2c3e50;
          font-size: 12px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }

  }

  &-poup {
    position: absolute;
    right: 0;
    top: 0;
    width: 334px;
    background: #FFFFFF;
    box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(29.99999943901511px);
    z-index: 601;
    padding: 20px;

    &-btns {
      text-align: center;

      &>button:first-child {
        margin-right: 20px;
      }
    }
  }
}
</style>