<template>
  <v-group :id="data.id" ref="shape">
    <v-group>
      <singleLine
        v-for="item in data.lines"
        :key="item.id"
        :line="item"
        :data="data"
        :add-mode="addMode"
        :can-edit="!initData && !operMode.mulSelection"
        :dragPointIds="dragPointIds"
        @add-point="(p) => addPointHandler(p, item)"
        @del-point="delPointHandler"
        @update-point="updatePointHandler"
        @update-before="updateBeforeHandler"
        @update="updateHandler"
        @del-line="delLineHandler(item)"
        @dragLineStart="dragstartLineHandler"
        @dragLine="dragLineHandler"
        @dragLineEnd="dragendLineHandler"
      />
    </v-group>
  </v-group>
</template>

<script lang="ts" setup>
import { onlyId } from "@/utils/shared.ts";
import { delPoint, LineData } from "./index.ts";
import singleLine from "./single-line.vue";
import { useInitData } from "./use-draw.ts";
import {
  genMoveLineHandler,
  getInitCtx,
  NLineDataCtx,
  normalLineData,
} from "./attach-server.ts";
import { computed, ref, watch } from "vue";
import { useZIndex } from "@/core/hook/use-layer.ts";
import { DC } from "@/deconstruction.js";
import { Group } from "konva/lib/Group";
import { useOperMode } from "@/core/hook/use-status.ts";
import { useMouseShapeStatus } from "@/core/hook/use-mouse-status.ts";
import { Pos } from "@/utils/math.ts";
import { useSnapConfig, useSnapResultInfo } from "@/core/hook/use-snap.ts";

const props = defineProps<{
  data: LineData;
  addMode?: boolean;
  canEdit?: boolean;
}>();

watch(
  () => props.data,
  (ndata, odata) => {
    console.log("data change", ndata, odata, ndata === odata);
  }
);

const operMode = useOperMode();
const initData = useInitData();
const emit = defineEmits<{
  (e: "updateShape"): void;
}>();

const data = computed(() => {
  if (!initData.value || props.addMode) return props.data;
  return initData.value;
});

const dragPointIds = ref<string[]>();
let track = false;
let ctx: NLineDataCtx;
const updateBeforeHandler = (ids: string[]) => {
  dragPointIds.value = ids;
  track = true;
  ctx = getInitCtx();
};

const delPointHandler = (p: LineData["points"][0]) => {
  delPoint(props.data, p.id, ctx);
};

const addPointHandler = (p: LineData["points"][0], l: LineData["lines"][0]) => {
  props.data.points.push(p);
  ctx.add.points[p.id] = p;
  delLineHandler(l);
  addLineHandler({ ...l, a: p.id, id: onlyId() });
  addLineHandler({ ...l, b: p.id, id: onlyId() });
};

const updatePointHandler = (p: LineData["points"][0]) => {
  const ndx = props.data.points.findIndex((pn) => pn.id === p.id);
  // props.data.points[ndx] = p;
  props.data.points[ndx].x = p.x;
  props.data.points[ndx].y = p.y;
  ctx.update.points[p.id] = props.data.points[ndx];
};
const delLineHandler = (l: LineData["lines"][0]) => {
  ctx.del.lines[l.id] = l;
  const ndx = props.data.lines.findIndex((ln) => ln.id === l.id);
  ~ndx && props.data.lines.splice(ndx, 1);
};
const addLineHandler = (l: LineData["lines"][0]) => {
  ctx.add.lines[l.id] = l;
  props.data.lines.push(l);
};

const updateHandler = () => {
  normalLineData(props.data, ctx);
  emit("updateShape");
  track = false;
  dragPointIds.value = undefined;
};

const resultInfo = useSnapResultInfo();
const snapConfig = useSnapConfig();
let handler: ReturnType<typeof genMoveLineHandler>;
const dragstartLineHandler = (line: LineData["lines"][0]) => {
  updateBeforeHandler([line.a, line.b]);
  handler = genMoveLineHandler(props.data, line.id, snapConfig, resultInfo, ctx);
};
const dragLineHandler = (_: any, ps: Pos[]) => {
  handler.move(ps);
};
const dragendLineHandler = () => {
  handler.end();
  updateHandler();
};

const shape = ref<DC<Group>>();
useZIndex(shape, data);
useMouseShapeStatus(shape);
</script>
