<template>
  <div class="page">
    <div class="flex">
      <div class="flex items-center">
        <span>场景：</span>
        <el-tree-select
          v-model="selectedShop"
          :data="scenesTree"
          :render-after-expand="false"
          placeholder="请选择场景"
          @change="changeShop"
        />
      </div>
    </div>
    <div class="paint-tool flex">
      <div class="camera-list">
        <div>
          <span class="label-text flex">相机列表：</span>
          <ElInput
            style="margin: 10px; width: 230px"
            placeholder="输入相机id或工位"
            v-model="searchKey"
            :suffix-icon="Search"
          />
        </div>
        <el-scrollbar style="height: calc(100% - 50px)">
          <div
            v-for="item in filterShopCameraList"
            :key="item.code"
            class="camera-item flex justify-start"
            :class="{ isAdded: isAddedToMap(item.code) }"
            @click="handleAddCamera(item.code)"
          >
            <span class="camera-id">{{ item.name }}</span>
            <span>{{ item.workSpaceName }}</span>
          </div>
        </el-scrollbar>
      </div>
      <div class="draw-container">
        <div style="display: flex; margin-bottom: 20px">
          <div>
            默认摄像头:
            <ElSelect v-model="defaultCameraId">
              <ElOption
                :key="item.value"
                :label="item.value"
                :value="item.value"
                v-for="item in cameraOptions"
              />
            </ElSelect>
          </div>

          <el-upload
            class="avatar-uploader flex justify-center items-center"
            action="/temp/api/layout/uploadPicture"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :with-credentials="true"
            name="file"
            :data="{ workshopId: selectedShopId }"
          >
            <el-button style="font-size: 12px">+ 更换/上传背景图片</el-button>
          </el-upload>

          <el-button
            @click="handleSave"
            style="margin-left: 40px"
            type="primary"
            :disabled="!selectedShopId"
            >保存布局</el-button
          >
        </div>
        <div>
          <div style="height: 20px; margin-bottom: 10px">
            <div v-if="selectedCamera">
              已选中相机<span>: {{ selectedCamera?.cameraId }}</span>
              <span style="margin-left: 20px">
                工位：{{ selectedCameraDetail?.workSpaceName }}
              </span>
            </div>
          </div>
        </div>
        <div style="overflow: auto">
          <canvas
            width="400"
            height="400"
            id="mapEditCanvas"
            style="border: 1px solid #ccc"
          ></canvas>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import useMiniMap from './use-mini-map';
  import { storeToRefs } from 'pinia';
  import { ElMessage, ElInput } from 'element-plus';
  import urlJoin from 'url-join';
  import { onMounted, ref, toRaw } from 'vue';
  import CameraMap, { CameraImage } from './MapBase/CameraMap';
  import { ElSelect, ElOption } from 'element-plus';
  import { updateMinMapViewLayoutApi } from '@/api/scene/scene';
  import { onUnmounted } from 'vue';
  import { useGlobSetting } from '@/hooks/setting';
  import { computed } from 'vue';
  import { Search } from '@element-plus/icons-vue';

  const miniMap = useMiniMap();
  const globSetting = useGlobSetting();
  const { selectedShop, scenesTree, shopCameraList, selectedShopId } = storeToRefs(miniMap);
  const { getScenesTree, getShowCameras, getMapLayout } = miniMap;

  let map: CameraMap;
  const selectedCamera = ref<CameraImage | null>(null);
  const cameraOptions = ref<{ label: string; value: string }[]>([]);
  const defaultCameraId = ref('');
  const searchKey = ref('');

  const handleAvatarSuccess = (e) => {
    const imgPath = e.data;
    const imgUrl = urlJoin(globSetting.imgUrl!, imgPath);
    map.uploadBg(imgUrl);
  };

  const changeShop = (newVal) => {
    const info = JSON.parse(newVal);
    console.log('info', info);
    if (info.parentId || info.parentId == 0) {
      ElMessage({
        message: '该场景暂无相机',
        type: 'error',
      });
      return;
    }
    getShowCameras();
    getMapLayout().then((res) => {
      if (!res) {
        map.clear();
        return;
      }
      defaultCameraId.value = res.defaultCameraId;
      map.loadFromJSON(res).then(() => {
        mapJSONToOptions();
        if (!defaultCameraId.value) {
          defaultCameraId.value = cameraOptions.value[0]?.value;
        }
      });
    });
  };

  onMounted(() => {
    getScenesTree(2);
    map = new CameraMap({ canvasId: 'mapEditCanvas', onSelect: onSelectCamera });
  });

  const keyupListener = (e) => {
    const keyCode = e.code;
    if (keyCode === 'Delete' || keyCode === 'Backspace') {
      if (selectedCamera.value) {
        handleDeleteCamera();
      }
    }
  };

  onMounted(() => {
    document.addEventListener('keyup', keyupListener);
  });

  onUnmounted(() => {
    document.removeEventListener('keyup', keyupListener);
  });

  const selectedCameraDetail = computed(() => {
    return shopCameraList.value.find((item) => item.code === selectedCamera.value?.cameraId);
  });

  const filterShopCameraList = computed(() => {
    const k = searchKey.value.trim();
    if (!k) return shopCameraList.value;
    return shopCameraList.value.filter((x) => x.code?.includes(k) || x.workSpaceName?.includes(k));
  });

  /** 摄像机是否已添加到底图 */
  const isAddedToMap = (cameraId: string): boolean => {
    return cameraOptions.value.some((x) => x.value === cameraId);
  };

  const handleAddCamera = (cameraId: string) => {
    if (map.hasCamera(cameraId)) {
      ElMessage.warning({ message: '相机已添加' });
      return;
    }
    map.addCamera(cameraId).then((cameraImg) => {
      onSelectCamera(cameraImg);
      mapJSONToOptions();
      if (!defaultCameraId.value) {
        defaultCameraId.value = cameraOptions.value[0]?.value;
      }
    });
  };

  const onSelectCamera = (cameraImg: CameraImage) => {
    console.log('onSelectCamera', cameraImg);
    selectedCamera.value = cameraImg;
  };

  const mapJSONToOptions = () => {
    const objects = map.toJSON()?.objects || [];
    console.log('objects', objects);
    cameraOptions.value = objects?.map((x) => ({
      label: x.cameraId,
      value: x.cameraId,
    }));
  };

  const handleSave = () => {
    const json = map.toJSON();
    console.log('save json', json);
    if (!json?.backgroundImage) {
      ElMessage.error('背景图片未添加');
      return;
    }
    const layout = JSON.stringify({ ...json, defaultCameraId: defaultCameraId.value });
    updateMinMapViewLayoutApi({ layout, targetId: selectedShopId.value }).then((res) => {
      console.log('updateMinMapViewLayoutApi', res);
      ElMessage.success('保存成功');
    });
  };

  const handleDeleteCamera = () => {
    if (!selectedCamera.value) return;
    map.removeCamera(toRaw(selectedCamera.value!));
    /** 如果删除的是默认选中的摄像头，那么先清空默认的摄像头再 */
    mapJSONToOptions();
    if (selectedCamera.value.cameraId === defaultCameraId.value) {
      defaultCameraId.value = cameraOptions.value[0]?.value;
    }
    selectedCamera.value = null;
  };
</script>

<style scoped>
  .page {
    margin: 10px 0;
    padding: 10px;
    background-color: #ffffff;
  }

  .avatar-uploader {
    /* width: 120px; */
    /* height: 30px; */
    /* border: 1px solid #eee; */
    border-radius: 4px;
    margin-left: 30px;
  }

  .paint-tool {
    height: calc(100vh - 200px);
    margin: 0 10px;
    margin-top: 20px;
    border: 1px solid #c0c4cc;
  }

  .camera-list {
    width: 250px;
    border-right: 1px solid #c0c4cc;
  }
  .label-text {
    font-size: 14px;
    font-weight: 600;
    margin: 10px 0 5px 10px;
  }
  .camera-item {
    padding: 10px 0 10px 10px;
    margin: 0 8px 1px 8px;
    border: 1px solid #c0c4cc;
    cursor: pointer;
  }
  .camera-id {
    width: 130px;
  }

  .draw-container {
    width: calc(100% - 300px);
    margin: 20px;
  }

  :deep(.avatar-uploader .el-upload) {
  }

  .isAdded {
    color: #409eff;
  }
</style>
