<template>
  <RightFillPano>
    <h3>{{ tagging?.title }}放置位置</h3>
    <Collapse v-model:activeKey="showId" ghost accordion expandIconPosition="end">
      <template v-for="(position, i) in positions" :key="position.id">
        <PositionSign
          v-show="!(unKeepAdding && position.id !== showId)"
          :position="position"
          :title="`位置${i + 1}`"
          @applyGlobal="(keys) => applyGlobal(position, keys)"
          @delete="deletePosition(position)"
          @show="showId = position.id"
        />
      </template>
    </Collapse>
    <Teleport to="#layout-app">
      <span
        @click="unKeepAdding ? unKeepAdding() : keepAdding()"
        class="pin-position strengthen fun-ctrl"
      >
        <ui-icon
          :style="{ color: unKeepAdding ? 'var(--color-main-normal)' : 'currentColor' }"
          type="pin1"
          size="22px"
        />
      </span>
    </Teleport>
  </RightFillPano>
</template>

<script lang="ts" setup>
import PositionSign from "./sign.vue";
import { router } from "@/router";
import { Dialog, Message } from "bill/index";
import { RightFillPano } from "@/layout";
import { asyncTimeout, debounce } from "@/utils";
import { useViewStack } from "@/hook";
import { flyTaggingPosition as flyTaggingPositionRaw } from "@/hook/use-fly";

import {
  computed,
  nextTick,
  onUnmounted,
  ref,
  shallowRef,
  watch,
  watchEffect,
} from "vue";
import { getTaggingPosNode, sdk, taggingsGroup } from "@/sdk";
import { custom, showTaggingPositionsStack } from "@/env";
import {
  autoSaveTaggings,
  getFuseModel,
  getFuseModelShowVariable,
  getTaggingPositions,
  taggingPositions,
  createTaggingPosition,
  getTagging,
  enterEdit,
} from "@/store";
import { Collapse } from "ant-design-vue";

import type { TaggingPosition } from "@/store";
import { clickListener } from "@/utils/event";
import { useCameraChange } from "@/hook/use-pixel";

const showId = ref<TaggingPosition["id"]>();
const tagging = computed(() => getTagging(router.currentRoute.value.params.id as string));
const positions = computed(() => tagging.value && getTaggingPositions(tagging.value));

onUnmounted(() => unKeepAdding.value && unKeepAdding.value());

useViewStack(autoSaveTaggings);
useViewStack(() => {
  taggingsGroup.changeCanMove(true);
  taggingsGroup.showDelete(true);
  enterEdit(() => router.back());
  return () => {
    taggingsGroup.changeCanMove(false);
    taggingsGroup.showDelete(false);
  };
});

watch(showId, (id) => {
  const position = positions.value?.find((item) => item.id === id);
  if (custom.showMode === "fuse") {
    position && flyTaggingPosition(position);
  }
});
const [pose] = useCameraChange(() => sdk.getPose());

watch(
  [
    showId,
    pose,
    () => {
      const pos = positions.value?.find((item) => item.id === showId.value);
      return [pos?.localPos, pos?.lineHeight];
    },
  ],
  debounce((a) => {
    const position = positions.value?.find((item) => item.id === showId.value);
    if (position) {
      position.pose = sdk.getPose({ modelId: position.modelId, isFlyToTag: true });
      console.log("set Pose", position.pose);
    }
  }, 300)
);

let pop: () => void;
const flyTaggingPosition = (position: TaggingPosition) => {
  pop && pop();
  const model = getFuseModel(position.modelId);
  if (!model || !getFuseModelShowVariable(model).value) {
    return;
  }

  pop = showTaggingPositionsStack.push(ref(new WeakSet([position])));
  flyTaggingPositionRaw(position);
};
onUnmounted(() => pop && pop());

const deletePosition = (position: TaggingPosition) => {
  const index = taggingPositions.value.indexOf(position);
  if (~index) {
    taggingPositions.value.splice(index, 1);
  }
};

const applyGlobal = async (position: TaggingPosition, keys: string | string[]) => {
  if (!(await Dialog.confirm("确定要将此属性应用到所有位置？"))) return;
  keys = Array.isArray(keys) ? keys : [keys];
  for (const current of positions.value!) {
    let val: any = current;
    let newVal: any = position;
    for (let i = 0; i < keys.length; i++) {
      if (i === keys.length - 1) {
        val[keys[i]] = newVal[keys[i]];
      } else {
        val = val[keys[i]];
        newVal = newVal[keys[i]];
      }
    }
  }
};

let unKeepAdding = shallowRef<() => void>();
const keepAdding = () => {
  unKeepAdding.value && unKeepAdding.value();
  sdk.startAddSth();
  const hide = Message.show({ msg: "请在模型上单击选择标签位置", type: "warning" });
  showId.value = void 0;

  const removeListener = clickListener(sdk.layout, async (pos) => {
    await nextTick();
    await asyncTimeout();
    const position = sdk.getPositionByScreen(pos);

    if (!position) {
      Message.error("当前位置无法添加");
    } else {
      const storePosition = createTaggingPosition({
        ...position,
        normal: position.localNormal,
        taggingId: tagging.value!.id,
      });
      taggingPositions.value.push(storePosition);
      showId.value = storePosition.id;
      nextTick(() => {
        getTaggingPosNode(storePosition)!.changeCanMove(true);
      });
    }
  });

  unKeepAdding.value = () => {
    hide();
    sdk.endAddSth();
    removeListener();
    unKeepAdding.value = void 0;
  };
};
keepAdding();
</script>

<style lang="scss" scoped>
h3 {
  font-family: Microsoft YaHei, Microsoft YaHei;
  font-weight: bold;
  font-size: 16px;
  color: #999999;
  margin-bottom: 4px;
}
.pin-position {
  position: absolute;
  left: 50%;
  transform: translate(-50%);
  width: 64px;
  height: 64px;
  background: rgba(27, 27, 28, 0.8);
  border-radius: 50%;
  bottom: 20px;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
<style lang="scss">
.position-group .group-title {
  margin-bottom: 0;
}
</style>
