import { useEditor } from "@/modules/editor";
import { Alignment } from "@ckeditor/ckeditor5-alignment";
import {
  Bold,
  Italic,
  Strikethrough,
  Underline,
} from "@ckeditor/ckeditor5-basic-styles";
import { InlineEditor } from "@ckeditor/ckeditor5-editor-inline";
import { Essentials } from "@ckeditor/ckeditor5-essentials";
import { FontColor, FontFamily, FontSize } from "@ckeditor/ckeditor5-font";
import { Link } from "@ckeditor/ckeditor5-link";
import { Paragraph } from "@ckeditor/ckeditor5-paragraph";
import { css } from "@linaria/core";
import LineHeight from "ckeditor5-line-height-latest/src/lineheight";
import { nextTick } from "process";
import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
import { string } from "vue-types";
import { useCompData } from ".";
import { View } from "../View";

function GetConfig() {
  const fontSizeOptions = [];
  const list = [12, 14, 16, 18, 20, 24, 28, 32, 38, 42, 46, 52, 60];
  for (const s of list) {
    fontSizeOptions.push({ title: s + "", model: s + "px" });
  }
  const fontFamilyOptions = [
    { title: "默认字体", model: "" },
    { title: "宋体", model: "宋体,Songti,STSong,serif" },
    { title: "黑体", model: "黑体,Heiti,STHeiti,sans-serif" },
    { title: "仿宋", model: "仿宋,FangSong,STFangsong,serif" },
    { title: "楷体", model: "楷体,KaiTi,STKaiti,sans-serif" },
  ];
  const config = {
    // updateSourceElementOnDestroy: true,
    language: "zh-cn",
    plugins: [
      Essentials,
      Bold,
      Italic,
      Link,
      Underline,
      Strikethrough,
      Paragraph,
      FontColor,
      FontSize,
      FontFamily,
      Alignment,
      LineHeight,
    ],
    fontSize: {
      options: fontSizeOptions,
      supportAllValues: true,
    },
    fontFamily: {
      options: fontFamilyOptions,
      supportAllValues: true,
    },
    lineHeight: {
      options: [1, 1.5, 2, 2.5, 3],
    },
    toolbar: {
      items: [
        // "undo",
        // "redo",
        // "|",
        "fontColor",
        "fontFamily",
        "fontSize",
        "lineHeight",
        "bold",
        "italic",
        "underline",
        "strikethrough",
        "|",
        "alignment",
        // "|",
        "link",
      ],
    },
  };
  return config;
}

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 }) {
    const inputRef = ref();
    let editorInstance = ref<InlineEditor>();
    const comp = useCompData(props.compId);
    const { store, actions, helper, controls } = useEditor();

    let blurCanceler: any = null;
    onMounted(() => {
      blurCanceler = blurHandle();
    });
    onUnmounted(() => {
      blurCanceler?.();
    });

    function isInCkBodyWrapper(dom: HTMLElement) {
      if (editorInstance.value) {
        const in1 =
          editorInstance.value.ui.view.toolbar.element?.contains(dom) ||
          editorInstance.value.ui.view.editable.element?.contains(dom);
        if (in1) return true;

        const ckBodyWrapper = document.querySelector(".ck-body-wrapper");
        if (ckBodyWrapper === dom || ckBodyWrapper?.contains(dom)) {
          return true;
        }
      }
      return false;
    }

    function blurHandle() {
      function blur(e: MouseEvent) {
        const target = e.target as HTMLElement;
        if (!editorInstance.value) return;

        if (isInCkBodyWrapper(target)) {
          e.stopPropagation();
          return;
        }
        actions.submitUpdate();
        emit("lost");
      }
      document.addEventListener("mousedown", blur, {
        capture: true,
      });
      return () => {
        document.removeEventListener("mousedown", blur, { capture: true });
      };
    }

    const preHeight = ref<number>(0);

    return () => (
      <ckeditor
        class={textStyle}
        ref={inputRef}
        editor={InlineEditor}
        onInput={(value: any) => {
          if (editorInstance.value && comp.value !== value) {
            actions.updateCompData(comp, "value", value);
            nextTick(() => {
              const h = helper.pxToDesignSize(inputRef.value?.$el.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) {
                console.log("changing=>", isChange);
                actions.selectObjs([]);
                setTimeout(() => {
                  actions.selectObjs([props.compId]);
                }, 0);
              }
            });
          }
        }}
        onReady={(editor: InlineEditor) => {
          editorInstance.value = editor;
          console.log("editor");
          editor.setData(comp.value);
          editor.focus();
          const range = document.createRange();
          range.selectNodeContents(inputRef.value.$el);
          const selection = window.getSelection();
          selection?.removeAllRanges();
          selection?.addRange(range);
        }}
        config={GetConfig()}
      />
    );
  },
});

const textStyle = css`
  font-size: 12px;
  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;
  }
`;
