import {
  useCursor,
  useDownKeys,
  useInstanceProps,
  useLayers,
  useMode,
  useStage,
} from "./use-global-vars.ts";
import { Stage } from "konva/lib/Stage";
import { useInteractiveProps } from "./use-interactive.ts";
import { useStore } from "../store/index.ts";
import { useViewer } from "./use-viewer.ts";
import { useGlobalResize, useListener } from "./use-event.ts";
import { useInteractiveDrawShapeAPI } from "./use-draw.ts";
import { useHistory } from "./use-history.ts";
import { reactive, watchEffect } from "vue";
import { usePaste } from "./use-paste.ts";
import { useMouseShapesStatus } from "./use-mouse-status.ts";
import { Mode } from "@/constant/mode.ts";
import { ElMessageBox } from "element-plus";
import { mergeFuns } from "@/utils/shared.ts";
import { themeColor } from "@/constant/help-style.ts";
import { isSvgString } from "@/utils/resource.ts";
import { useResourceHandler } from "./use-fetch.ts";

export const useAutoService = () => {
  // 自动粘贴服务
  const paste = usePaste();
	const drawAPI = useInteractiveDrawShapeAPI()
	const resourceHandler = useResourceHandler()
  paste.push({
    ["text/plain"]: {
      async handler(pos, val) {
				if (isSvgString(val)) {
					const url = await resourceHandler(val, 'svg')
					drawAPI.addShape('icon', { url, stroke: themeColor }, pos, true)
				} else {
					drawAPI.addShape('text', { content: val }, pos, true)
				}
      },
      type: "string",
    },
    ["image"]: {
      async handler(pos, val, type) {
				const url = await resourceHandler(val, type)
				if (type.includes('svg')) {
					drawAPI.addShape('icon', { url, stroke: themeColor }, pos, true)
				} else {
					drawAPI.addShape('image', { url }, pos, true)
				}
      },
      type: "file",
    },
  });

  // 自动退出添加模式
  const { quitDrawShape } = useInteractiveDrawShapeAPI();
  useListener(
    "contextmenu",
    (ev) => {
      if (ev.button === 2) {
        quitDrawShape();
      }
    },
    document.documentElement
  );

  // 鼠标自动变化服务
  const status = useMouseShapesStatus();
  const downKeys = useDownKeys();
  const mode = useMode();
  const cursor = useCursor();

  watchEffect((onCleanup) => {
    let style: string | null = null;
    if (downKeys.has(" ")) {
      style = "pointer";
    } else if (mode.include(Mode.update)) {
      style = "move";
    } else if (status.hovers.length) {
      style = "pointer";
    }

    if (style) {
      cursor.push(style);
      onCleanup(() => cursor.pop());
    }
  });

  // 自动保存历史及恢复服务
  const history = useHistory();
  const instanceProps = useInstanceProps();
  const init = (id: any) => {
		const quitHooks: (() => void)[] = []
    if (!id) return quitHooks;

		const unloadHandler = () => {
      if (history.hasRedo.value || history.hasUndo.value) {
        history.saveLocal();
      }
    }
    history.setLocalId(id);
    window.addEventListener("beforeunload", unloadHandler);
		quitHooks.push(() => window.removeEventListener('beforeunload', unloadHandler))

    if (!history.hasLocal()) return quitHooks;

		let isOpen = true
		ElMessageBox.confirm("检测到有历史数据，是否要恢复？", {
			type: "info",
			confirmButtonText: "恢复",
			cancelButtonText: "取消",
		}).then(() => {
      history.loadLocalStorage();
		}).catch(() => {
      history.clearLocal();
		}).finally (() => {
			isOpen = false
		})
		quitHooks.push(() => isOpen && ElMessageBox.close())
		return quitHooks;
  };
  watchEffect((onCleanup) => {
		onCleanup(mergeFuns(init(instanceProps.get().id)))
	});
};

export type DrawExpose = ReturnType<typeof useExpose>;
type PickParams<K extends keyof Stage, O extends string> = Stage[K] extends (
  ...args: any
) => any
  ? Omit<Required<Parameters<Stage[K]>>[0], O>
  : never;

export const useExpose = () => {
  const mode = useMode();
  const interactiveProps = useInteractiveProps();
  const stage = useStage();
  const layers = useLayers();
  const store = useStore();
  const history = useHistory();
  const viewer = useViewer().viewer;
  const { updateSize } = useGlobalResize();
  const config = reactive({
    showGrid: true,
    showLabelLine: true,
  });

  const exposeBlob = (config?: PickParams<"toBlob", "callback">) => {
    const $stage = stage.value!.getStage();
    return new Promise<Blob>((resolve) => {
      $stage.toBlob({ ...config, resolve } as any);
    });
  };

  const toggleHit = () => {
    if (!layers.value) return;
    layers.value.forEach((layer) => {
      layer.toggleHitCanvas();
    });
  };

  return {
    ...useInteractiveDrawShapeAPI(),
    get stage() {
      const $store = stage.value!.getStage();
      return $store;
    },
    exposeBlob,
    toggleHit,
    updateSize,
    history,
    store,
    mode,
    getData() {
      return store.data;
    },
    viewer,
    presetAdd: interactiveProps,
    config,
  };
};
