<template>
  <Teleport :to="mount">
    <textarea
      ref="textarea"
      :style="styles"
      @input="() => text = textarea!.value"
      @blur="quit"
      @focus="focusHandler"
      @click.stop
      >{{ text }}</textarea
    >
  </Teleport>
</template>

<script lang="ts" setup>
import { useStage } from "@/core/hook/use-global-vars";
import { Text } from "konva/lib/shapes/Text";
import { computed, onUnmounted, ref, watch } from "vue";
import { DomMountId } from "@/constant/index.ts";
import { useViewer, useViewerTransform } from "@/core/hook/use-viewer";
import { listener } from "@/utils/event";
import { Transform } from "konva/lib/Util";
import { useGetPointerTextNdx } from "./util";

const props = defineProps<{ shape: Text }>();
const emit = defineEmits<{ (e: "submit", text: string): void }>();

const isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const isEdge = (document as any).documentMode || /Edge/.test(navigator.userAgent);
const textarea = ref<HTMLTextAreaElement>();
const stage = useStage();
const $stage = stage.value?.getNode()!;
const text = ref(props.shape.text());
const mount = document.querySelector(`#${DomMountId}`) as HTMLDivElement;

const quit = () => emit("submit", text.value);
const focusHandler = (ev: any) => {
  ev.preventDefault();
  mount.scroll(0, 0);
};

listener(mount, "keydown", (ev) => {
  if (ev.key === "Escape") {
    textarea.value?.blur();
  }
});

const refreshMat = () => {
  const dom = textarea.value!;
  let mat = props.shape.getAbsoluteTransform();
  if (isFirefox) {
    mat = new Transform()
      .translate(0, -2 - Math.round(props.shape.fontSize() / 20))
      .multiply(mat);
  } else {
    mat = new Transform().translate(0, -0.5).multiply(mat);
  }
  dom.style.transform = `matrix(${mat.m.join(",")})`;
};

const refreshSize = () => {
  const dom = textarea.value!;
  let newWidth = props.shape.width();
  if (isSafari || isFirefox) {
    newWidth = Math.ceil(newWidth);
  } else if (isEdge) {
    newWidth += 1;
  }
  dom.style.width = newWidth + "px";
  dom.style.height = props.shape.height() + props.shape.fontSize() / 2 + "px";
};

const getPointerTextNdx = useGetPointerTextNdx();
const focusToPointer = () => {
  if (!textarea.value) return;
  const ndx = getPointerTextNdx(props.shape);
  textarea.value.focus();
  textarea.value.setSelectionRange(ndx, ndx);
};

const styles = computed(() => {
  const shape = props.shape;
  return {
    fontSize: shape.fontSize() + "px",
    lineHeight: shape.lineHeight(),
    fontFamily: shape.fontFamily(),
    textAlign: shape.align() as CanvasTextAlign,
    color: shape.fill().toString(),
  };
});

const viewer = useViewer();
const refresh = () => {
  refreshSize();
  refreshMat();

  // const textRect = textarea.value!.getBoundingClientRect();
  // const contRect = $stage.container().getBoundingClientRect();
  // const textR = textRect.x + textRect.width;
  // const textB = textRect.y + textRect.height;
  // const contR = contRect.x + contRect.width;
  // const contB = contRect.y + contRect.height;

  // if (
  //   textR > contR ||
  //   textB > contB ||
  //   textRect.x < contRect.x ||
  //   textRect.y < contRect.y
  // ) {
  //   viewer.viewer.scalePixel(
  //     { x: contRect.x + contRect.width / 2, y: contRect.x + contRect.height / 2 },
  //     0.8
  //   );
  // }
};

const transform = useViewerTransform();
watch(
  text,
  () => {
    props.shape.text(text.value);
    props.shape.fire("bound-change");
  },
  { flush: "sync" }
);
watch(
  () => [textarea.value, text.value, transform.value],
  () => textarea.value && refresh()
);

watch(
  () => [props.shape, textarea.value] as const,
  ([shape, dom]) => {
    if (shape && dom) {
      focusToPointer();
    }
  }
);

let unListener: () => void;
const timeout = setTimeout(() => {
  unListener = listener($stage.container(), "click", quit);
}, 16);

onUnmounted(() => {
  if (unListener!) {
    unListener();
  } else {
    clearTimeout(timeout);
  }
});
</script>

<style lang="scss" scoped>
textarea {
  position: absolute;
  border: 0;
  padding: 0;
  margin: 0;
  overflow: hidden;
  background: none;
  resize: none;
  pointer-events: all;
  outline: none;
  word-break: break-all;
  transform-origin: left top;
}

div {
  position: absolute;
  background: rgba(0, 0, 0, 0.4);
  left: 0;
  top: 0;
  transform-origin: left top;
}
</style>
