<template>
  <v-group ref="shape" :id="data.id">
    <v-arrow
      name="arrow"
      v-for="(_, ndx) in data.points.length - 1"
      :config="{
        ...data,
        zIndex: undefined,
        hitFunc: hitFunc,
        stroke: data.fill,
        fill: data.fill,
        hitStrokeWidth: data.strokeWidth + 10,
        pointerWidth: data.pointerLength,
        closed: false,
        id: void 0,
        points: flatPositions([data.points[ndx], data.points[ndx + 1]]),
        ...eConfig,
        opacity: addMode ? 0.3 : data.opacity,
      }"
    />
    <v-circle
      v-if="zeroEq(lineLen(data.points[0], data.points[1]))"
      :config="{
        ...data.points[0],
        radius: data.strokeWidth * 2,
        opacity: 0,
        fill: 'red',
        offset: { x: data.strokeWidth, y: 0 },
      }"
    />

    <!-- <EditPolygon
      :data="{ ...data, stroke: data.fill, strokeWidth: data.strokeWidth + 5 }"
      :shape="shape"
      :addMode="false"
      :canEdit="canEdit"
      @update:position="(data) => emit('update:position', data)"
      @update="emit('update')"
      @deletePoint="(ndx) => emit('deletePoint', ndx)"
      @addPoint="(data) => emit('addPoint', data)"
      v-if="shape"
    /> -->

    <v-group>
      <template
        v-if="(status.hover || status.active || addMode) && !operMode.mulSelection"
      >
        <Point
          v-for="(_, ndx) in data.points"
          :size="data.strokeWidth + 6"
          :points="data.points"
          :ndx="ndx"
          :closed="false"
          :id="data.id"
          :disable="addMode"
          :color="data.fill"
          @update:position="(p) => emit('update:position', { ndx, val: p })"
          @dragend="emit('update')"
          notDelete
        />
      </template>
    </v-group>

    <SizeLine
      v-if="config.showComponentSize"
      :points="data.points"
      :strokeWidth="data.strokeWidth"
      :stroke="data.fill"
    />
  </v-group>
</template>

<script lang="ts" setup>
import SizeLine from "../share/size-line.vue";
// import EditPolygon from "../share/edit-polygon.vue";
import Point from "../share/edit-point.vue";
import { ArrowData, defaultStyle, PointerPosition } from "./index.ts";
import { DC } from "@/deconstruction.js";
import { computed, ref, watchEffect } from "vue";
import { flatPositions } from "@/utils/shared.ts";
import { Arrow } from "konva/lib/shapes/Arrow";
import { lineLen, Pos, zeroEq } from "@/utils/math.ts";
import { LineConfig } from "konva/lib/shapes/Line";
import { Group } from "konva/lib/Group";
import { useConfig } from "@/core/hook/use-config.ts";
import { useMouseShapeStatus } from "@/core/hook/use-mouse-status.ts";
import { useOperMode } from "@/core/hook/use-status.ts";

const props = defineProps<{ data: ArrowData; canEdit?: boolean; addMode?: boolean }>();
const emit = defineEmits<{
  (e: "update:position", data: { ndx: number; val: Pos }): void;
  (e: "update"): void;
  (e: "deletePoint", ndx: number): void;
  (e: "addPoint", data: { ndx: number; val: Pos }): void;
}>();

const shape = ref<DC<Group>>();
const config = useConfig();
const data = computed(() => ({ ...defaultStyle, ...props.data }));
const hitFunc: LineConfig["hitFunc"] = (con, shape) => {
  con.beginPath();
  con.moveTo(data.value.points[0].x, data.value.points[0].y);
  for (let i = 1; i < data.value.points.length; i++) {
    con.lineTo(data.value.points[i].x, data.value.points[i].y);
  }
  con.closePath();
  con.fillStrokeShape(shape);
};
const status = useMouseShapeStatus(computed(() => shape.value));
const operMode = useOperMode();

watchEffect(
  (onCleanup) => {
    const $shape = shape.value?.getNode();
    if ($shape) {
      const timeout = setTimeout(() => {
        $shape.findOne<Arrow>(".arrow")?.fill(data.value.fill);
      });
      onCleanup(() => clearTimeout(timeout));
    }
  },
  { flush: "post" }
);

const eConfig = computed(() => {
  const position =
    "pointerPosition" in data.value
      ? data.value.pointerPosition!
      : defaultStyle.pointerPosition;
  const eStart = [PointerPosition.all, PointerPosition.start].includes(position);
  const eEnd = [PointerPosition.all, PointerPosition.end].includes(position);

  return {
    pointerAtBeginning: eStart,
    pointerAtEnding: eEnd,
  };
});

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