<template>
  <TempIcon :data="tData" :ref="(e: any) => shape = e?.shape" />
  <PropertyUpdate
    :describes="describes"
    :data="data"
    :target="shape"
    @delete="emit('delShape')"
    @change="emit('updateShape', { ...data })"
  />
  <Operate :target="shape" :menus="operateMenus" />
</template>

<script lang="ts" setup>
import TempIcon from "./temp-icon.vue";
import {
  LineIconData,
  getMouseStyle,
  defaultStyle,
  matResponse,
  getLineIconMat,
  getSnapLine,
  getLineIconEndpoints,
  isRangInner,
} from "./index.ts";
import { useComponentStatus } from "@/core/hook/use-component.ts";
import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
import { Transform } from "konva/lib/Util";
import {
  useCustomTransformer,
  useGetTransformerOperType,
} from "@/core/hook/use-transformer.ts";
import { Group } from "konva/lib/Group";
import { Rect } from "konva/lib/shapes/Rect";
import { setShapeTransform } from "@/utils/shape.ts";
import { useStore } from "@/core/store/index.ts";
import { usePointerPos } from "@/core/hook/use-global-vars.ts";
import { useViewerInvertTransform } from "@/core/hook/use-viewer.ts";
import { computed, nextTick, watch } from "vue";
import { useHistory } from "@/core/hook/use-history.ts";
import {
  eqPoint,
  line2IncludedAngle,
  lineInner,
  lineLen,
  lineVector,
  Pos,
  zeroEq,
} from "@/utils/math.ts";
import { asyncTimeout, copy } from "@/utils/shared.ts";
import { useTestPoints } from "@/core/hook/use-debugger.ts";

const props = defineProps<{ data: LineIconData }>();
const emit = defineEmits<{
  (e: "updateShape", value: LineIconData): void;
  (e: "addShape", value: LineIconData): void;
  (e: "delShape"): void;
}>();

const store = useStore();
const getOperType = useGetTransformerOperType();
const viewMat = useViewerInvertTransform();
const pos = usePointerPos();
const testPoints = useTestPoints();
const { shape, tData, data, operateMenus, describes } = useComponentStatus({
  emit,
  props,
  getMouseStyle,
  transformType: "custom",
  selfData: true,
  customTransform(callback, shape, data) {
    let prevInvMat: Transform;
    let posOffset: Pos | null = null;
    return useCustomTransformer(shape, data, {
      getRepShape() {
        const group = new Group();
        const rect = new Rect();
        group.add(rect);
        const update = () => {
          const mat = getLineIconMat(getSnapLine(store, data.value)!, data.value);
          const width = Math.abs(data.value.endLen - data.value.startLen);
          const height = data.value.height;
          prevInvMat = mat;
          rect.width(width);
          rect.height(height);
          rect.offset({ x: width / 2, y: height / 2 });
          setShapeTransform(group, mat);
        };
        update();
        return { shape: group, update };
      },
      handler(data, mat) {
        if (pos.value && !getOperType()) {
          // if (!posOffset) {
          //   const real = viewMat.value.point(pos.value);
          //   const prevDec = prevInvMat.decompose();
          //   posOffset = {
          //     x: real.x - prevDec.x,
          //     y: real.y - prevDec.y,
          //   };
          //   testPoints.value = [
          //     {
          //       x: real.x - posOffset.x,
          //       y: real.y - posOffset.y,
          //     },
          //   ];
          // }
          const rpos = viewMat.value.point({
            x: pos.value.x,
            y: pos.value.y,
          });
          const m = mat.m;
          m[4] = rpos.x;
          m[5] = rpos.y;
          // m[4] = rpos.x - posOffset.x;
          // m[5] = rpos.y - posOffset.y;
          mat = new Transform(m);
        }
        matResponse({
          data,
          mat: mat,
          operType: getOperType(),
          store,
        });

        return true;
      },
      callback() {
        posOffset = null;
        callback();
      },
      openSnap: false,
      transformerConfig: {
        flipEnabled: true,
        rotateEnabled: false,
        enabledAnchors: ["middle-left", "middle-right"],
        boundBoxFunc: (oldBox, newBox) => {
          if (newBox.width < 5) {
            return oldBox;
          } else {
            return newBox;
          }
        },
      },
    });
  },
  defaultStyle,
  copyHandler(_, data) {
    const snapLine = getSnapLine(store, data)!;
    const line = getLineIconEndpoints(getSnapLine(store, data)!, data);
    const vector = lineVector(line);
    const move = vector.multiplyScalar(lineLen(line[0], line[1]));
    const mat = new Transform()
      .translate(move.x, move.y)
      .multiply(getLineIconMat(snapLine, data));
    return matResponse({ data, mat, store });
  },
  propertys: ["name", "fill", "stroke", "strokeWidth"],
});

const lineRaw = computed(() => {
  const line = store.getTypeItems("line")[0];
  return line.lines.find((item) => item.id === props.data.lineId);
});
const line = computed(() => getSnapLine(store, props.data));
const history = useHistory();
watch(
  () => ({
    line: lineRaw.value && (copy(line.value) as Pos[]),
    width: lineRaw.value?.strokeWidth,
  }),
  (newv, oldv) => {
    const line = newv.line;
    const oldLine = oldv?.line;
    history.preventTrack(() => {
      if (!line) {
        return emit("delShape");
      }
      if (!oldLine) return;

      const eq0 = eqPoint(oldLine[0], line[0]);
      const eq1 = eqPoint(oldLine[1], line[1]);
      if (!eq0 || !eq1) {
        if (eq0 === eq1) {
          let newLen = lineLen(line[0], line[1]);
          if (zeroEq(newLen - lineLen(oldLine[0], oldLine[1]))) {
            shape.value?.getNode().fire("bound-change");
            return;
          }
          if (!isRangInner(line, data.value)) {
            emit("delShape");
            return;
          }
        } else {
          // 联动
          const startNdx = eq0 ? 0 : 1;
          const endNdx = eq0 ? 1 : 0;
          const rotate = line2IncludedAngle(
            [oldLine[startNdx], oldLine[endNdx]],
            [line[startNdx], line[endNdx]]
          );
          const mat = new Transform()
            .translate(line[startNdx].x, line[startNdx].y)
            .rotate(rotate)
            .translate(-line[startNdx].x, -line[startNdx].y);

          const endPoints = getLineIconEndpoints(oldLine, data.value).map((p) =>
            mat.point(p)
          );

          if (lineInner(line, endPoints[0]) && lineInner(line, endPoints[1])) {
            emit("updateShape", {
              ...data.value,
              startLen: lineLen(line[0], endPoints[0]),
              endLen: lineLen(line[0], endPoints[1]),
            });
          } else {
            emit("delShape");
            return;
          }
        }
      } else if (newv.width !== oldv.width && newv.width && props.data.type === "full") {
        emit("updateShape", { ...data.value, height: newv.width });
      }
      nextTick(() => {
        shape.value?.getNode().fire("bound-change");
      });
    });
  },
  { immediate: true, flush: "pre" }
);
operateMenus.splice(0, 2);
operateMenus.splice(1, 2);
if (props.data.type === "align-bottom" || props.data.type === "align-bottom-fix") {
  operateMenus.splice(
    operateMenus.length - 2,
    0,
    // {
    //   label: "内外翻转",
    //   handler: () => {
    //     emit("updateShape", {
    //       ...data.value,
    //       openSide: data.value.openSide === "LEFT" ? "RIGHT" : "LEFT",
    //     });
    //   },
    // },
    {
      label: "翻转",
      handler: () => {
        emit("updateShape", {
          ...data.value,
          openSide: data.value.openSide === "LEFT" ? "RIGHT" : "LEFT",
          startLen: data.value.endLen,
          endLen: data.value.startLen,
        });
      },
    }
  );
}
</script>
