<template>
  <v-rect
    :config="{
      width: size?.width,
      height: height,
      fill: background ? background : '#000',
      opacity: opacity,
      ...bgConfig,
    }"
  />

  <component
    :is="itemsRenderer"
    :items="items"
    :top="top"
    :activeNdx="active ? items.indexOf(active) : -1"
    :ref="(r: any) => itemShapes = r ? r.shapes : []"
  />
  <template v-for="(itemShape, i) in itemShapes">
    <Operate
      v-if="itemShape"
      :target="itemShape"
      :menus="[
        {
          label: '复制',
          handler: () => copyHandler(i),
        },
        {
          label: '删除',
          handler: () => delHandler(i),
        },
      ]"
    />
  </template>
</template>

<script lang="ts" setup>
import { computed, ref, watch, watchEffect } from "vue";
import {
  useDrag,
  useGlobalResize,
  useGlobalVar,
  useViewerInvertTransform,
} from "../drawing/hook";
import { Transform } from "konva/lib/Util";
import { DC, EntityShape } from "../drawing/dec";
import Operate from "../drawing/operate.vue";
import { checkTLItem, getAddTLItemTime, TLItem } from "./check";

const { misPixel } = useGlobalVar();
const { size } = useGlobalResize();

const props = defineProps<{
  items: TLItem[];
  itemsRenderer: any;
  background?: string;
  height: number;
  opacity: number;
  top: number;
  active?: TLItem;
}>();
const emit = defineEmits<{
  (e: "update:active", data: TLItem | undefined): void;
  (e: "update", data: { ndx: number; time: number }): void;
  (e: "add", data: any): void;
  (e: "del", ndx: number): void;
}>();

const invMat = useViewerInvertTransform();
const bgConfig = computed(() => {
  return new Transform()
    .multiply(invMat.value.copy())
    .translate(0, props.top)
    .decompose();
});

const itemShapes = ref<DC<EntityShape>[]>([]);
const { drag } = useDrag(itemShapes);
let total = { x: 0, y: 0 };
watch(drag, (drag) => {
  if (!drag) {
    total = { x: 0, y: 0 };
    return;
  }
  const cur = props.items[drag.ndx];
  if (
    checkTLItem(
      props.items,
      { ...cur, time: cur.time + (total.x + drag.x) / misPixel },
      drag.ndx
    )
  ) {
    const curX = cur.time * misPixel + total.x + drag.x;
    emit("update", { ndx: drag.ndx, time: curX / misPixel });
    total = { x: 0, y: 0 };
  } else {
    total.x += drag.x;
    total.y += drag.y;
  }
});

watchEffect((onCleanup) => {
  for (let i = 0; i < itemShapes.value.length; i++) {
    const $shape = itemShapes.value[i]?.getNode();
    if (!$shape) continue;
    $shape.on("click.uactive", () => {
      emit("update:active", props.active === props.items[i] ? undefined : props.items[i]);
    });
    onCleanup(() => $shape.off("click.uactive"));
  }
});

const copyHandler = (ndx: number) => {
  const newFrame = {
    ...props.items[ndx],
    time: getAddTLItemTime(props.items, ndx, props.items[ndx].duration),
  };
  emit("add", newFrame);
};

const delHandler = (ndx: number) => {
  emit("del", ndx);
};
</script>
