<template>
  <template v-for="(shape, i) in status.actives" :key="shape._id">
    <v-rect
      :ref="(rect: any) => rects[i] = rect"
      :config="boxs.get(shape)"
      :strokeWidth="4"
      :opacity="0.3"
      :stroke="themeColor"
      :dash="[10, 10]"
      :listening="false"
      v-if="boxs.get(shape)"
    />
  </template>
</template>

<script lang="ts" setup>
import { nextTick, reactive, ref, watch, watchEffect } from "vue";
import { useMouseShapesStatus } from "../hook/use-mouse-status";
import { IRect } from "konva/lib/types";
import { useViewer } from "../hook/use-viewer";
import { DC, EntityShape } from "@/deconstruction";
import { themeColor } from "@/constant/help-style";
import { Rect } from "konva/lib/shapes/Rect";
import { useDashAnimation } from "../hook/use-animation";
import { useGetComponentData } from "../hook/use-component";

const status = useMouseShapesStatus();
const boxs = reactive(new WeakMap<EntityShape, IRect>());
const padding = 8;

const updateBox = ($shape: EntityShape) => {
  const rect = $shape.getClientRect();
  boxs.set($shape, {
    x: rect.x - padding,
    y: rect.y - padding,
    width: rect.width + padding * 2,
    height: rect.height + padding * 2,
  });
};

type OnCleanup = (cleanupFn: () => void) => void;

const getComponentData = useGetComponentData();
const shapeListener = (shape: EntityShape, onCleanup: OnCleanup) => {
  const update = async () => {
    await nextTick();
    updateBox(shape);
  };

  const repShape = shape.repShape || shape;
  repShape.on("transform", update);
  shape.on("bound-change", update);

  watch(() => getComponentData(shape).value, update);
  update();
  onCleanup(() => {
    repShape.off("transform", update);
    shape.off("bound-change", update);
  });
};

watchEffect(
  (onCleanup) => {
    console.error(status.actives)
    status.actives.forEach((shape) => shapeListener(shape, onCleanup));
  },
  { flush: "pre" }
);

watch(useViewer().transform, () => {
  for (const $shape of status.actives) {
    updateBox($shape);
  }
});

// animation
const rects = ref<DC<Rect>[]>([]);
useDashAnimation(rects);
</script>
