import { useEditor } from "@/modules/editor";
import { css } from "@linaria/core";
import { nextTick } from "process";
import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
import { string } from "vue-types";
import { useCompData } from ".";
import { View } from "../View";
import HeadlessEditor from "./EditorCustom";
export const Component = defineComponent({
  props: {
    compId: string().def(""),
  },
  setup(props) {
    const comp = useCompData(props.compId);
    const { store, actions } = useEditor();

    const state = reactive({
      editableId: "",
    });

    if (store.isEditMode) {
      actions.on("textFocus", function (compId, focus) {
        if (compId != props.compId) return;
        if (focus) {
          state.editableId = "" + Date.now();
          return;
        }
        state.editableId = "";
      });
    }

    return () => (
      <View
        class={[textStyle]}
        compId={props.compId}
        onDblclick={() => {
          if (store.isEditMode) {
            state.editableId = "" + Date.now();
          }
        }}
      >
        {state.editableId ? (
          <EditorComp
            compId={props.compId}
            key={state.editableId}
            onLost={() => {
              state.editableId = "";
            }}
          />
        ) : (
          <div
            innerHTML={comp.value}
            class={[textStyle, store.isEditMode && `pointer-events-none`]}
          />
        )}
      </View>
    );
  },
});

const EditorComp = defineComponent({
  props: {
    compId: string().isRequired,
  },
  emits: ["lost"],

  setup(props, { emit }) {
    let editorRefVal = ref<HeadlessEditor>().value;
    const comp = useCompData(props.compId);
    const { store, actions, helper, controls } = useEditor();

    let blurCanceler: any = null;

    onUnmounted(() => {
      blurCanceler?.();
    });
    const preHeight = ref<number>(0);
    const initHeight = () => {
      const dom: HTMLElement | null = document.querySelector(
        `#editor_${props.compId}`
      );
      if (!dom) {
        return false;
      }
      const h = helper.pxToDesignSize(dom.clientHeight);
      const isChange = Math.abs(preHeight.value - h) > 1;
      preHeight.value = h;
      actions.updateCompData(comp, "layout.size.1", preHeight.value);
      helper.extendStreamCard(store.currStreamCardId);
      if (isChange) {
        actions.selectObjs([]);
        setTimeout(() => {
          actions.selectObjs([props.compId]);
        }, 0);
      }
    };
    function isInCkBodyWrapper(dom: HTMLElement) {
      const out = { in: false, stop: true };

      if (editorRefVal) {
        const in1 =
          editorRefVal.ui.view.toolbar.element?.contains(dom) ||
          editorRefVal.ui.view.editable.element?.contains(dom);
        if (in1) {
          out.in = true;
          return out;
        }
        const ckBodyWrapper = document.querySelector(".ck-body-wrapper");
        if (ckBodyWrapper === dom || ckBodyWrapper?.contains(dom)) {
          out.in = true;
          return out;
        }
      }

      let n = 0;
      let curr: any = dom;
      do {
        if (
          curr.id == "text_toolform" ||
          curr.classList.contains("pcr-app") ||
          curr.classList.contains("editor_toolbar_drop") ||
          curr.classList.contains("ant-select-dropdown")
        ) {
          out.in = true;
          out.stop = false;
          return out;
        }
        curr = curr.parentElement;
        n += 1;
        if (n > 10) break;
      } while (curr);
      return out;
    }

    function blurHandle() {
      function blur(e: MouseEvent) {
        const target = e.target as HTMLElement;

        if (!editorRefVal) return;
        const test = isInCkBodyWrapper(target);
        if (test.in) {
          if (test.stop) {
            e.stopPropagation();
          }
          return;
        }
        actions.submitUpdate();
        emit("lost");
      }

      document.addEventListener("mousedown", blur, {
        capture: true,
      });
      return () => {
        document.removeEventListener("mousedown", blur, { capture: true });
      };
    }
    const initEditor = async () => {
      const dom: HTMLElement | null = document.querySelector(
        `#editor_${props.compId}`
      );
      if (!dom) {
        return;
      }
      editorRefVal = await HeadlessEditor.create(dom);
      editorRefVal.setData(comp.value);
      editorRefVal.focus();
      const range = document.createRange();
      range.selectNodeContents(dom);
      const selection = window.getSelection();
      selection?.removeAllRanges();
      selection?.addRange(range);

      editorRefVal.model.document.on("change:data", () => {
        const value = editorRefVal?.getData();

        if (comp.value !== value) {
          actions.updateCompData(comp, "value", value);
          nextTick(() => {
            const element = editorRefVal?.ui.view.editable.element || null;
            if (!element) {
              return;
            }
            const h = helper.pxToDesignSize(element.clientHeight);
            const isChange = Math.abs(preHeight.value - h) > 1;
            preHeight.value = h;
            actions.updateCompDatas(
              comp,
              ["value", "layout.size.1"],
              [value, preHeight.value]
            );
            helper.extendStreamCard(store.currStreamCardId);
            if (isChange) {
              actions.selectObjs([]);
              setTimeout(() => {
                actions.selectObjs([props.compId]);
              }, 0);
            }
          });
        }
      });
      controls.textEditorCtrl.setCurrEditor(editorRefVal);
    };

    onMounted(() => {
      initEditor();
      blurCanceler = blurHandle();
      nextTick(() => {
        initHeight();
      });
    });
    return () => {
      return <div class={textStyle} id={`editor_${props.compId}`}></div>;
    };
  },
});

const textStyle = css`
  font-size: 14px;
  width: 100%;
  color: #666;
  word-break: break-all;

  p {
    margin: 0;
  }

  .ck.ck-editor__editable_inline {
    cursor: text;
    overflow: hidden;
    border: none !important;

    > :last-child,
    > :first-child {
      margin-top: 0;
      margin-bottom: 0;
    }
    padding: 0 !important;
  }
`;
