import { throttle } from "lodash-es";
import { Controller, PID, Eventes, Paragraph } from "@tingwujs/core";

// toUpdate: 表示段落发生修改，并且需要翻译
// toTranslateOnly: 表示段落没有修改，但只需要翻译
// ----------
export interface ParagraphChangeStore {
  toAdd: Record<PID, boolean>;
  toUpdate: Record<PID, boolean>;
  toRemove: Record<PID, boolean>;
  toRemoveParagraphs: Record<PID, Paragraph>;
  toTranslateOnly: Record<PID, boolean>;
  toUpdateWithoutTranslate: Record<PID, boolean>;
}

export type UpdateParagraphCallback = (store: ParagraphChangeStore) => Promise<void>;

const getInitializeStore = (): ParagraphChangeStore => {
  return {
    toAdd: {},
    toUpdate: {},
    toRemove: {},
    toRemoveParagraphs: {},
    toTranslateOnly: {},
    toUpdateWithoutTranslate: {},
  };
};

export const createParagraphChangeThrottler = (
  controller: Controller,
  callback: UpdateParagraphCallback
) => {
  let store: ParagraphChangeStore = getInitializeStore();
  let storeChanged = false;
  let loading = false;

  const submitParagraphChange = async () => {
    if (loading || !storeChanged) {
      return;
    }
    const originStore = store;
    store = getInitializeStore();
    storeChanged = false;

    try {
      loading = true;
      await callback(originStore);
    } finally {
      loading = false;
    }

    if (storeChanged) {
      submitParagraphChange();
    }
  };

  const throttleSubmitParagraphChange = throttle(submitParagraphChange, 1000);

  const handleParagraphChange = (event: Eventes["paragraphChangeSpecific"]) => {
    const {
      unfixToFixedPids,
      updateParagraphUserChangedPids,
      addParagraphPids,
      updateParagraphPids,
      removeParagraphPids,
      removeParagraphs = {},
      textNotChangePids = [],
      userChangePids = [],
    } = event;

    addParagraphPids.forEach((pid, index) => {
      const paragraph = controller.getParagraph(pid);
      if (paragraph && !paragraph.isUnfix) {
        store.toAdd[pid] = true;
        storeChanged = true;
      }

      if (
        paragraph &&
        paragraph.isUnfix &&
        index === addParagraphPids.length - 1 &&
        controller.getRealTimeLivingMode()
      ) {
        store.toAdd = {};
        storeChanged = false;
      }
    });

    updateParagraphPids.forEach(pid => {
      const paragraph = controller.getParagraph(pid);
      if (paragraph && paragraph.isUnfix) {
        return;
      }
      if (
        unfixToFixedPids.indexOf(pid) > -1 &&
        updateParagraphUserChangedPids.indexOf(pid) === -1
      ) {
        return;
      }
      store.toUpdate[pid] = true;
      if (
        unfixToFixedPids.indexOf(pid) === 1 &&
        (textNotChangePids.includes(pid) || userChangePids.includes(pid))
      ) {
        store.toUpdateWithoutTranslate[pid] = true;
      }
      delete store.toTranslateOnly[pid];
      storeChanged = true;
    });

    removeParagraphPids.forEach(pid => {
      if (store.toAdd[pid]) {
        delete store.toAdd[pid];
        storeChanged = true;
        return;
      }

      delete store.toUpdate[pid];
      if (store.toUpdateWithoutTranslate[pid]) {
        delete store.toUpdateWithoutTranslate[pid];
      }
      store.toRemove[pid] = true;
      store.toRemoveParagraphs[pid] = removeParagraphs[pid];
      storeChanged = true;
    });

    throttleSubmitParagraphChange();
  };

  const handleTranslate = (event: Eventes["paragraphNeedTranslate"]) => {
    const { pid } = event;
    if (!store.toUpdate[pid]) {
      store.toTranslateOnly[pid] = true;
      storeChanged = true;
    }
    console.log(store);
    throttleSubmitParagraphChange();
  };

  const offCallback1 = controller.on("paragraphChangeSpecific", handleParagraphChange);
  const offCallback2 = controller.on("paragraphNeedTranslate", handleTranslate);

  return () => {
    offCallback1();
    offCallback2();
  };
};
