<template>
  <!-- @dragstart="emit('dragLineStart', props.line)"
    @update:line="(ps) => emit('dragLine', props.line, ps)"
    @dragend="emit('dragLineEnd', props.line)" -->
  <EditLine
    :ref="(d: any) => shape = d?.shape"
    :data="lineData"
    :opacity="0"
    :points="points"
    :closed="false"
    :id="line.id"
    :disablePoint="true"
    :ndx="0"
    @dragstart="dragstartHandler(points.map((item) => item.id))"
    @update:line="
      (p) => {
        emit('updatePoint', { ...points[0], ...p[0] });
        emit('updatePoint', { ...points[1], ...p[1] });
      }
    "
    @dragend="dragendHandler"
    @add-point="addPoint"
  />

  <v-line
    v-for="polygon in polygons"
    :config="{
      opacity: drawProps ? 0.7 : 1,
      points: flatPositions(polygon),
      fill: isDrawIng ? themeColor : style.stroke,
      closed: true,
      listening: false,
    }"
  />
  <!-- v-if="status.active" -->
  <!-- <v-text :config="{ ...pointsCenter(points), text: line.id }" /> -->
  <template
    v-if="
      status.active ||
      config.showComponentSize ||
      isDrawIng ||
      dragPointIds?.includes(line.a) ||
      dragPointIds?.includes(line.b)
    "
  >
    <v-group>
      <template v-if="gd.steps.value.length">
        <SizeLine
          :points="line"
          :strokeWidth="style.strokeWidth"
          :stroke="style.stroke"
          v-for="line in [...gd.steps.value, ...gd.subSteps.value]"
        />
      </template>
      <SizeLine
        :points="points"
        :strokeWidth="style.strokeWidth"
        :stroke="style.stroke"
        v-else
      />
    </v-group>
  </template>

  <PropertyUpdate
    :describes="describes"
    :data="line"
    :target="shape"
    :name="shapeName"
    @change="
      () => {
        emit('updateBefore', []);
        emit('updateLine', { ...line });
        emit('update');
      }
    "
    @delete="delHandler"
  />
  <Operate :target="shape" :menus="menus" />

  <template v-if="drawProps">
    <SingleLine
      :data="drawProps.data"
      :line="drawProps.prev"
      :drawMode="drawProps.point"
      :get-extend-polygon="drawGetExtendPolygon"
    />
    <singlePoint
      :data="drawProps.data"
      :line="drawProps.prev"
      :drawMode="drawProps.point"
    />
    <SingleLine
      :data="drawProps.data"
      :line="drawProps.next"
      :drawMode="drawProps.point"
      :get-extend-polygon="drawGetExtendPolygon"
    />
    <singlePoint
      :data="drawProps.data"
      :line="drawProps.next"
      :drawMode="drawProps.point"
    />
  </template>
</template>

<script lang="ts" setup>
import EditLine from "../share/edit-line.vue";
import singlePoint from "./single-point.vue";
import { computed, ref } from "vue";
import { getMouseStyle, LineData, LineDataLine, shapeName } from "./index.ts";
import { flatPositions, onlyId } from "@/utils/shared.ts";
import { pointsCenter, Pos } from "@/utils/math.ts";
import { Line } from "konva/lib/shapes/Line";
import { DC } from "@/deconstruction.js";
import SizeLine from "../share/size-line.vue";
import { useConfig } from "@/core/hook/use-config.ts";
import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
import {
  useAnimationMouseStyle,
  useMouseShapeStatus,
} from "@/core/hook/use-mouse-status.ts";
import { themeColor } from "@/constant";
import { useGetDiffLineIconPolygons, useGetExtendPolygon } from "./attach-view.ts";
import {
  getLinePoints,
  useDrawLinePoint,
  useLineDataSnapInfos,
  useLineDescribes,
} from "./attach-server.ts";
import { useStore } from "@/core/store/index.ts";
import { useHistory } from "@/core/hook/use-history.ts";

const props = defineProps<{
  line: LineDataLine;
  addMode?: boolean;
  canEdit?: boolean;
  data: LineData;
  dragPointIds?: string[];
  drawMode?: LineData["points"][number];
  getExtendPolygon: (line: LineDataLine) => Pos[];
}>();

const emit = defineEmits<{
  (e: "updatePoint", value: LineData["points"][number]): void;
  (e: "addPoint", value: LineData["points"][number]): void;
  (e: "addLine", value: LineDataLine): void;
  (e: "delLine"): void;
  (e: "updateLine", value: LineDataLine): void;
  (e: "updateBefore", value: string[]): void;
  (e: "update"): void;

  (e: "dragLineStart", value: LineDataLine): void;
  (e: "dragLine", line: LineDataLine, move: Pos[]): void;
  (e: "dragLineEnd", value: LineDataLine): void;
}>();

const polygon = computed(() => props.getExtendPolygon(line.value));
const line = computed(() => props.line);
const points = computed(() => getLinePoints(props.data, props.line));
const gd = useGetDiffLineIconPolygons(line.value, points);
const polygons = computed(() => gd.diff(polygon.value));

const shape = ref<DC<Line>>();
const lineData = computed(() => props.line);
const describes = useLineDescribes(lineData);

const delHandler = () => {
  emit("updateBefore", [props.line.a, props.line.b]);
  emit("delLine");
  emit("update");
};

const store = useStore();
const history = useHistory();
const { drawProps, enter: enterDrawLinePoint } = useDrawLinePoint(
  computed(() => props.data),
  props.line,
  (data) => {
    emit("updateBefore", [props.line.a, props.line.b]);
    emit("addPoint", data.point);
    emit("addLine", data.prev);
    emit("addLine", data.next);
    emit("delLine");
    history.preventTrack(() => {
      data.oldIcons.forEach((icon) => store.delItem("lineIcon", icon.id));
      store.addItems("lineIcon", data.newIcons);
    });
    emit("update");
  }
);

const drawGetExtendPolygon = useGetExtendPolygon(computed(() => drawProps.value?.data));

const menus = [
  { label: "加点", handler: enterDrawLinePoint },
  { label: "删除", handler: delHandler },
];

const status = useMouseShapeStatus(shape);
const [style] = useAnimationMouseStyle({
  shape,
  getMouseStyle,
  data: lineData as any,
});

const isDrawIng = computed(
  () =>
    (props.addMode &&
      props.data.lines.indexOf(props.line) === props.data.lines.length - 1) ||
    props.drawMode
);

const addPoint = (pos: Pos) => {
  emit("updateBefore", []);
  emit("addPoint", { ...points.value[0], ...pos, id: onlyId() });
  emit("update");
};

const lDataSnap = useLineDataSnapInfos();
const config = useConfig();
const dragstartHandler = (eIds: string[]) => {
  emit("updateBefore", eIds);
  lDataSnap.update(eIds);
};
const dragendHandler = () => {
  emit("update");
  lDataSnap.clear();
};

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