<template>
  <v-rect
    :config="{ ...data, opacity: 1, zIndex: undefined, strokeScaleEnable: true }"
    ref="shape"
  />
</template>

<script lang="ts" setup>
import { defaultStyle, GroupData } from "./index.ts";
import { computed, nextTick, onUnmounted, ref, watch } from "vue";
import { DC, EntityShape } from "@/deconstruction.js";
import { Rect, RectConfig } from "konva/lib/shapes/Rect";
import { useViewerInvertTransform } from "@/core/hook/use-viewer.ts";
import { useStage } from "@/core/hook/use-global-vars.ts";
import { useOnComponentBoundChange } from "@/core/hook/use-component.ts";
import { debounce } from "@/utils/shared.ts";

const props = defineProps<{
  data: GroupData;
  addMode?: boolean;
  autoUpdate?: boolean;
}>();
const shape = ref<DC<Rect>>();
const data = computed(() => ({ ...defaultStyle, ...props.data }));

const stage = useStage();
const getGroupShapes = () => {
  const $stage = stage.value?.getNode();
  if (!$stage) return;
  const shapes: EntityShape[] = [];
  for (const id of data.value.ids) {
    const $shape = $stage!.findOne(`#${id}`)!;
    if (!$shape || $shape.attrs.disableGroupOper) continue;
    shapes.push($shape as EntityShape);
  }
  return shapes;
};

const invMat = useViewerInvertTransform();

const updateBound = () => {
  const shapes = $shapes.value;
  if (!shapes?.length) {
    console.error("!shapes");
    return;
  }
  let lx = Number.MAX_VALUE;
  let ly = Number.MAX_VALUE;
  let rx = Number.MIN_VALUE;
  let ry = Number.MIN_VALUE;

  for (const shape of shapes) {
    if (!shape) continue;

    const rect = shape.getClientRect();
    if (rect.x < lx) {
      lx = rect.x;
    }
    if (rect.y < ly) {
      ly = rect.y;
    }
    if (rect.x + rect.width > rx) {
      rx = rect.x + rect.width;
    }
    if (rect.y + rect.height > ry) {
      ry = rect.y + rect.height;
    }
  }

  const pixelStart = invMat.value.point({ x: lx, y: ly });
  const pixelEnd = invMat.value.point({ x: rx, y: ry });
  lx = pixelStart.x;
  ly = pixelStart.y;
  rx = pixelEnd.x;
  ry = pixelEnd.y;
  const config: RectConfig = {
    x: lx,
    y: ly,
    width: rx - lx,
    height: ry - ly,
    rotation: 0,
    scaleX: 1,
    scaleY: 1,
  };
  const $shape = shape.value?.getNode() as any;
  if ($shape) {
    for (const key in config) {
      $shape[key](config[key]);
    }
    nextTick(() => $shape.fire("bound-change"));
  }
};

watch(
  () => data.value.ids.length,
  () => nextTick(updateBound),
  { immediate: true }
);

const { on } = useOnComponentBoundChange();
const $shapes = computed(getGroupShapes);
const syncUpdateBound = debounce(updateBound, 0);
watch(
  () => {
    return (
      data.value.ids.join(",") +
      (props.autoUpdate ? "1" : "0") +
      (data.value.listening ? "1" : "0") +
      (stage.value ? "1" : "0")
    );
  },
  (_a, _b, onCleanup) => {
    if (props.autoUpdate) {
      onCleanup(
        on(
          $shapes,
          () => {
            props.autoUpdate && syncUpdateBound();
          },
          false
        )
      );
    }
  },
  { immediate: true }
);

onUnmounted(() => console.error("des temp-group"));

defineExpose({
  get shape() {
    return shape.value;
  },
  updateBound,
  getGroupShapes,
});
</script>
