import { Controller, Eventes } from "../index";
import { P } from "../../persist";
import mockData from "./mock/nfixRemoveParagraphByAddFixParagraph.json";

// interface Frame extends P {
//   partial: boolean;
// }
// type Frames = Frame[];

const sleep = (time: number) => new Promise(resolve => setTimeout(resolve, time));

describe("nfixRemoveParagraphByAddFixParagraph", () => {
  const controller = new Controller();
  controller.setLivingMode(true);
  controller.injectSpeakersGetter(() => []);
  controller.injectSpeakersSetter(() => {});
  let store: any = {
    toAdd: {},
    toUpdate: {},
    toRemove: {},
    toRemoveParagraphs: {},
    toTranslateOnly: {},
  };
  let storeChanged = false;
  let loading = false;
  let savePayload: P[];

  const handleSaveMeeting = (data: any) => {
    const { toUpdate, toAdd, toRemoveParagraphs } = data;

    const payload: { pg: P[] } = {
      pg: [],
    };

    const keys: Record<string, boolean> = {
      ...toUpdate,
      ...toAdd,
    };

    const pids = Object.keys(keys);
    const toRemovePids = Object.keys(toRemoveParagraphs);

    pids.forEach(pid => {
      const p = controller.getPByPid(pid);
      if (p) {
        payload.pg.push(p);
      }
    });

    toRemovePids.forEach(pid => {
      const para = toRemoveParagraphs[pid];
      payload.pg.push({
        pi: pid,
        ui: para.uid,
        sc: [],
      });
    });

    if (payload.pg.length === 0) {
      return;
    }

    savePayload = payload.pg;
  };

  const submitParagraphChange = () => {
    if (loading || !storeChanged) {
      return;
    }
    const originStore = store;
    store = {
      toAdd: {},
      toUpdate: {},
      toRemove: {},
      toRemoveParagraphs: {},
      toTranslateOnly: {},
    };
    storeChanged = false;

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

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

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

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

    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;
      delete store.toTranslateOnly[pid];
      storeChanged = true;
    });

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

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

    submitParagraphChange();
  };

  // 以前的ParagraphChange处理逻辑（本测试用例必现删除段落现象）
  // const processParagraphFrames = (pg: Frames) => {
  //   pg.forEach((item) => {
  //     const { partial, pi, sc, ui } = item;
  //     const paragraph = controller.getParagraph(pi);
  //     const words = controller.getWordsBySces(sc);
  //     if (partial) {
  //       if (!paragraph) {
  //         controller.addUnfixParagraph(pi, ui);
  //       }
  //       controller.appendWords(pi, words);
  //     } else if (!paragraph) {
  //       controller.addUnfixParagraph(pi, ui);
  //       controller.appendWords(pi, words);
  //       controller.addFixParagraph(pi);
  //     } else {
  //       controller.appendWords(pi, words);
  //       controller.addFixParagraph(pi);
  //     }
  //   });
  // };

  test("addFixParagraph", async () => {
    controller.on("paragraphChangeSpecific", handleParagraphChange);

    // 18000-18670（unfix中）
    // 18000-18400（fix & 丢失）
    // 18410-18690（下一段）
    mockData.forEach(async frames => {
      const pid = frames[0].pi;
      const words = [...(controller.getWords(pid) || [])];

      controller.processParagraphFrames(frames);
      if (frames.length > 1 && !frames[0].partial && frames[1].partial) {
        await sleep(2000);
      }

      const deleteP = savePayload && savePayload.find(({ sc }) => sc.length === 0);
      if (deleteP && deleteP.pi === pid) {
        const saveWords = savePayload.reduce((_res, { sc }) => [..._res, ...sc], [] as P["sc"]);
        expect(saveWords).toContainEqual(words[0]);
      }
    });

    return await sleep(0);
  });
});
