<template>
  <div class="draw-tools-container">
    <div class="draw-item" @mouseover="showColorSelect = true" @mouseleave="showColorSelect = false">
      <div class="item-label">画笔选择</div>
      <i class="color-box" :style="{ backgroundColor: colorList[drawerColorIndex]?.value }" />
      <!--弹窗选择器-->
      <div v-show="showColorSelect" ref="selectBoxRef" class="select-box" style="top: -123px; padding-bottom: 20px">
        <div class="box-content">
          <div
            v-for="(item, index) in colorList"
            :key="index"
            :class="mouseToolState.drawType === item.value ? 'select-item active' : 'select-item'"
            @click="selectColor(index)"
          >
            <i class="color-box" :style="{ backgroundColor: item.value }" />
            <span>{{ item.label }}</span>
          </div>
        </div>
      </div>
    </div>
    <div class="draw-item" @mouseover="showDrawTypeSelect = true" @mouseleave="showDrawTypeSelect = false">
      <div class="item-label">框面类型</div>
      <!--弹窗选择器-->
      <div v-show="showDrawTypeSelect" ref="selectBoxRef2" class="select-box" style="top: -64px; padding-bottom: 20px">
        <div class="box-content">
          <div
            v-for="(item, index) in drawTypeList"
            :key="index"
            :class="mouseToolState.drawType === item.value ? 'select-item active' : 'select-item'"
            @click="selectDrawType(index)"
          >
            <span>{{ item.label }}</span>
          </div>
        </div>
      </div>
    </div>
    <div class="draw-item" @mouseover="showGraphicsTypeSelect = true" @mouseleave="showGraphicsTypeSelect = false">
      <div class="item-label">图像类型</div>
      <!--弹窗选择器-151-->
      <div v-show="showGraphicsTypeSelect" ref="selectBoxRef2" class="select-box" style="top: -91px; padding-bottom: 20px">
        <div class="box-content">
          <div
            v-for="(item, index) in graphicsTypeList"
            :key="index"
            :class="mouseToolState.graphicsType === item.value ? 'select-item active' : 'select-item'"
            @click="selectGraphicsType(index)"
          >
            <span>{{ item.label }}</span>
          </div>
        </div>
      </div>
    </div>
    <div class="draw-item" @click="openDraw">{{ mouseToolState.drawing ? '关闭绘制' : '开启绘制' }}</div>
    <div class="draw-item" @click="handleUndo">撤销</div>
  </div>
</template>

<script lang="ts" setup name="DrawTools">
import { useHistory } from '@/hooks/useHistory';
import { nanoid } from 'nanoid';
import { deepClone } from '@/utils';
import * as turf from '@turf/turf';
import Overlay from 'ol/Overlay';

interface ListItem {
  label: string;
  value: string;
}
const props = defineProps({
  activeMap: String
});
const AMapType = ['vectorgraph', 'satellite'];
const getDrawTool = inject('getDrawTool');
const getMap = inject('getMap');
const getMapUtils = inject('getMapUtils');
const emits = defineEmits(['handleAnalysisData']);
const { currentState, commit, undo, history, future } = useHistory();
const mouseToolState = reactive({
  drawing: false,
  color: '#f80102',
  // 1线框 2区域
  drawType: '1',
  // 图形形状  circle圆形 rectangle矩形 polygon多边形
  graphicsType: 'circle'
});
let popup;
let map = computed(() => {
  return getMap();
});
let mapUtils = computed(() => {
  return getMapUtils();
});
watch(
  mouseToolState,
  () => {
    const drawTool = getDrawTool();
    if (mouseToolState.drawing) {
      drawOptions.color = mouseToolState.color;
      drawOptions.drawType = mouseToolState.drawType;
      drawOptions.graphicsType = mouseToolState.graphicsType;
      drawTool.drawGraphics2(drawOptions);
      if (AMapType.includes(props.activeMap)) {
        drawTool.getMouseTool().on('draw', onDraw);
      } else {
        drawTool.getMouseTool().on('drawend', onDraw2);
        map.value.un('click', onMapClick);
      }
    } else {
      mouseToolState.drawing = false;
      drawTool.closeDraw();
      if (!AMapType.includes(props.activeMap)) {
        map.value.on('click', onMapClick);
      }
    }
  },
  {
    deep: true
  }
);
const drawOptions = reactive({
  color: '#f80102',
  // 1线框 2区域
  drawType: '1',
  // 图形形状  circle圆形 rectangle矩形 polygon多边形
  graphicsType: 'circle'
});
const selectBoxRef = ref(null);
const selectBoxRef2 = ref(null);
const selectBoxRef3 = ref(null);

// 显示画笔选择弹窗
let showColorSelect = ref(false);
// 画笔颜色索引
let drawerColorIndex = ref(0);
// 画笔颜色列表
const colorList: ListItem[] = reactive([
  { label: '红色', value: '#f80102' },
  { label: '橙色', value: '#f4511e' },
  { label: '蓝色', value: '#0197f8' },
  { label: '绿色', value: '#42b884' }
]);
// 选中颜色
const selectColor = (index) => {
  drawerColorIndex.value = index;
  mouseToolState.color = colorList[index].value;
  showColorSelect.value = false;
};
const overlays = [];
const overlaysData = [];
// 点击颜色选择之外
onClickOutside(selectBoxRef, () => {
  if (!showColorSelect.value) return;
  showColorSelect.value = false;
});

// 绘制类型列表
const drawTypeList: ListItem[] = reactive([
  { label: '线框', value: '1' },
  { label: '面框', value: '2' }
]);
// 显示隐藏绘制类型弹窗
let showDrawTypeSelect = ref(false);

// 选择
const selectDrawType = (index) => {
  mouseToolState.drawType = drawTypeList[index].value;
  showDrawTypeSelect.value = false;
};
// 点击绘制类型选择之外
onClickOutside(selectBoxRef2, () => {
  if (!showDrawTypeSelect.value) return;
  showDrawTypeSelect.value = false;
});

// 绘制图形列表
const graphicsTypeList: ListItem[] = reactive([
  { label: '圆形', value: 'circle' },
  { label: '矩形', value: 'rectangle' },
  { label: '多边形', value: 'polygon' }
  // { label: '索套', value: 'freePolygon' }
]);
// 显隐图像类型弹窗
let showGraphicsTypeSelect = ref(false);

// 选择
const selectGraphicsType = (index) => {
  mouseToolState.graphicsType = graphicsTypeList[index].value;
  showGraphicsTypeSelect.value = false;
};
// 点击绘制类型选择之外
onClickOutside(selectBoxRef3, () => {
  if (!showGraphicsTypeSelect.value) return;
  showGraphicsTypeSelect.value = false;
});

// 开启结束绘制
const openDraw = () => {
  mouseToolState.drawing = !mouseToolState.drawing;
};
// 高德地图绘制结束
const onDraw = (event) => {
  const obj = event.obj;
  const id = nanoid();
  obj._opts.extData = {
    id: id
  };
  const data: any = {
    id: id,
    type: drawOptions.graphicsType,
    color: obj._opts.strokeColor,
    drawType: obj._opts.fillOpacity === 0 ? '1' : '2'
  };
  if (data.type === 'circle') {
    data.center = [obj.getCenter().lng, obj.getCenter().lat];
    data.radius = obj.getRadius();
  }
  const path = obj.getPath();
  // 将AMap.LngLat对象数组转换为经纬度数组
  const pathArr = path.map((lngLat) => {
    // 返回经度和纬度的数组
    return [lngLat.lng, lngLat.lat];
  });
  data.path = pathArr;
  overlays.push(obj);
  overlaysData.push(data);
  commit(deepClone(overlaysData));
  // 右击进入编辑
  obj.on('rightclick', handleRightClick);
  analysisSpatial(data);
  // 点击空间分析
  obj.on('click', function () {
    // 没在编辑时
    if (!mouseToolState.drawing) {
      analysisSpatial(data);
    }
  });
};
// 粤政图绘制结束
const onDraw2 = (event) => {
  const feature = event.feature;
  const geometry = feature.getGeometry();
  const geometryType = geometry.getType();
  const id = nanoid();
  feature.set('id', id);
  feature.set('dotType', 'analysisSpatial');
  const data: any = {
    id: id,
    type: drawOptions.graphicsType,
    color: drawOptions.color,
    drawType: drawOptions.drawType
  };
  feature.set('extraData', data);
  if (geometryType === 'Circle') {
    data.center = geometry.getCenter();
    data.radius = geometry.getRadius();
    const data2 = turf.sector(data.center, data.radius, 0, 360);
    const pathArr = data2.geometry.coordinates[0];
    data.path = pathArr;
  } else if (geometryType === 'Polygon') {
    const coordinates = geometry.getCoordinates();
    data.path = coordinates[0];
  }
  overlays.push(feature);
  overlaysData.push(data);
  commit(deepClone(overlaysData));
  // 右击进入编辑
  let map = getMap();
  map.on('contextmenu', handleRightClick2);
  analysisSpatial(data);
};
let rightClickObj;
// 图形右击事件
let initContextMenu = false;
const handleRightClick = (event) => {
  rightClickObj = event.target;
  const contextMenu = getDrawTool().getContextMenu();
  if (!initContextMenu) {
    // 右键删除按钮
    contextMenu.addItem(
      '删除',
      function () {
        contextMenu.close();
        deleteGraphics();
      },
      0
    );
    initContextMenu = true;
  }
  contextMenu.open(getMap(), event.lnglat);
};
const handleRightClick2 = (event) => {
  event.preventDefault(); // 阻止默认的右键菜单弹出
  map.value.un('click', onMapClick);
  if (popup) {
    map.value.removeOverlay(popup);
    popup = undefined;
  }
  rightClickObj = map.value.forEachFeatureAtPixel(event.pixel, (feature2) => {
    return feature2;
  });
  let dotType = rightClickObj.get('dotType');
  if (!!rightClickObj && dotType === 'analysisSpatial') {
    const dom = document.createElement('div');
    const dom2 = document.createElement('div');
    dom.id = 'analysisSpatial-popup';
    dom2.className = 'menu-item';
    dom2.innerHTML = '删除';
    dom2.onclick = function () {
      map.value.on('click', onMapClick);
      deleteGraphics();
    };
    dom.appendChild(dom2);
    popup = new Overlay({
      element: dom,
      autoPan: true,
      positioning: 'bottom-right',
      stopEvent: false,
      offset: [0, 0]
    });

    const geometry = rightClickObj.getGeometry();
    const geometryType = geometry.getType();
    let coordinate = [];
    if (geometryType === 'Circle') {
      coordinate = geometry.getCenter();
    } else {
      const points = geometry.getCoordinates();
      const features = turf.points(points[0]);
      const center = turf.center(features);
      if (center && center.geometry && center.geometry.coordinates) {
        coordinate = center.geometry.coordinates;
      }
    }
    popup.setPosition(coordinate);
    map.value.addOverlay(popup);
  }
};
// 删除图形
const deleteGraphics = () => {
  let id;
  if (AMapType.includes(props.activeMap)) {
    id = rightClickObj.getExtData()?.id;
  } else {
    unMapClick();
    id = rightClickObj.get('id');
  }
  if (!!id) {
    for (let i = 0; i < overlays.length; i++) {
      const overlay = Array.isArray(overlays[i]) ? overlays[i][0] : overlays[i];
      const itemId = AMapType.includes(props.activeMap) ? overlay?.getExtData().id : overlay.get('id');
      if (itemId === id) {
        removeOverlayByIndex(i);
        commit(deepClone(overlaysData));
        rightClickObj = null;
      }
    }
  }
};
// 撤销绘制
const handleUndo = () => {
  mouseToolState.drawing = false;
  const previous = history.value[history.value.length - 2];
  if (history.value.length > 1) {
    if (currentState.value.length > previous.length) {
      // 撤销新增
      removeOverlayByIndex(currentState.value.length - 1);
    } else {
      let restoreData;
      for (let i = 0; i < previous.length; i++) {
        let index = 0;
        for (let k = 0; k < currentState.value.length; k++) {
          if (previous[i].id !== currentState.value[k].id) {
            index++;
          } else {
            break;
          }
        }
        if (index === previous.length - 1) {
          restoreData = previous[i];
          break;
        }
      }
      if (restoreData) {
        const newData = {
          type: restoreData.type,
          path: restoreData.path,
          strokeColor: restoreData.color,
          strokeOpacity: 1,
          strokeWeight: '1',
          fillColor: restoreData.color,
          fillOpacity: restoreData.drawType === '1' ? '0' : '0.5'
        };
        if (restoreData.type === 'circle') {
          newData.center = restoreData.center;
          newData.radius = restoreData.radius;
        }
        let obj;
        if (AMapType.includes(props.activeMap)) {
          obj = getDrawTool().createGraphics(newData);
        } else {
          obj = getDrawTool().createGraphics(newData);
        }
        if (!!obj) {
          overlays.push(obj);
        }
      }
    }
    undo();

    console.log(history.value, future.value, currentState.value);
  }
};
// 根据索引移除覆盖物
const removeOverlayByIndex = (index: number) => {
  const map = getMap();
  if (AMapType.includes(props.activeMap)) {
    if (Array.isArray(overlays[index])) {
      overlays[index].forEach((overlay) => {
        // 移除地图上覆盖物
        map.remove(overlay);
      });
    } else {
      // 移除地图上覆盖物
      map.remove(overlays[index]);
    }
  } else {
    if (Array.isArray(overlays[index])) {
      overlays[index].forEach((overlay) => {
        // 移除地图上覆盖物
        mapUtils.value.getDrawVector().getSource().removeFeature(overlay);
      });
    } else {
      // 移除地图上覆盖物
      mapUtils.value.getDrawVector().getSource().removeFeature(overlays[index]);
    }
  }

  overlays.splice(index, 1);
  overlaysData.splice(index, 1);
};
let selectedScope = reactive({});
// 空间分析数据
const analysisSpatial = (data) => {
  // 已选中的范围
  if (selectedScope[data.id]) {
    delete selectedScope[data.id];
    if (JSON.stringify(selectedScope) === '{}') {
      // rightMenuRef.value.clickContractMenu();
      return;
    }
  } else {
    selectedScope[data.id] = data;
  }
  let location = [];
  for (let key in selectedScope) {
    let itemLocation = [];
    if (selectedScope[key].path && selectedScope[key].path.length > 1) {
      selectedScope[key].path.forEach((item) => {
        itemLocation.push({
          x: item[0],
          y: item[1]
        });
      });
      itemLocation.push(itemLocation[0]);
      location.push(itemLocation);
    }
  }
  emits('handleAnalysisData', location);
};
const onMapClick = (event) => {
  // 没在编辑时
  if (!mouseToolState.drawing && event.pixel) {
    const feature = map.value.forEachFeatureAtPixel(event.pixel, (feature2) => {
      return feature2;
    });
    const data = feature.get('extraData');
    analysisSpatial(data);
  }
  unMapClick(event);
};
const unMapClick = (event) => {
  const overlayElement = popup?.getElement();
  const isClickOnOverlay =
    event && overlayElement && (overlayElement.contains(event.originalEvent.target) || overlayElement === event.originalEvent.target);
  if (!isClickOnOverlay && popup) {
    map.value.removeOverlay(popup);
    popup = undefined;
  }
};
onMounted(() => {
  if (!AMapType.includes(props.activeMap)) {
    map.value.on('click', onMapClick);
  }
});
onBeforeUnmount(() => {
  if (overlays && overlays.length > 0) {
    overlays.forEach((overlay) => {
      if (AMapType.includes(props.activeMap)) {
        overlay.setMap(null);
      } else {
        mapUtils.value.getDrawVector().getSource().removeFeature(overlay);
      }
    });
  }
  if (!AMapType.includes(props.activeMap)) {
    map.value.un('click', onMapClick);
  }
});
</script>

<style lang="scss" scoped>
.draw-tools-container {
  position: absolute;
  right: 65px;
  bottom: 177px;
  background-color: #304468;
  border-radius: 5px;
  display: flex;
  color: #fff;
  font-size: 14px;
  padding: 8px 0;
  .draw-item {
    display: flex;
    align-items: center;
    position: relative;
    padding: 0 10px;
    cursor: pointer;
    border-left: 1px solid #3a74be;
    &:first-child {
      border-left: none;
    }
    .item-label {
      margin-right: 10px;
    }
    .select-box {
      position: absolute;
      left: 0;
      z-index: 7;
      width: 100%;
      .box-content {
        background-color: #102341;
      }
      .select-item {
        display: flex;
        align-items: center;
        cursor: pointer;
        padding: 4px 10px;
        &:hover {
          background-color: rgba(22, 73, 142, 0.5);
        }
        &:first-child {
          margin-left: 0;
        }
      }
      .color-box {
        margin-right: 5px;
      }
    }
  }
  .color-box {
    display: block;
    width: 20px;
    height: 20px;
    cursor: pointer;
    border-radius: 3px;
  }
}
.active {
  background-color: rgba(22, 73, 142, 0.5);
}
</style>
