import { AnyOperation, createOperation } from "../persist";
import { Book } from "./book";

export const invertOp = (op: AnyOperation): AnyOperation => {
  if (op.action === "updateWord") {
    const { pid, wid, oldValue, newValue } = op.payload;
    return createOperation("updateWord", {
      pid,
      wid,
      newValue: oldValue,
      oldValue: newValue,
    });
  } else if (op.action === "updateWords") {
    const { pid, oldValue, newValue } = op.payload;
    return createOperation("updateWords", {
      pid,
      newValue: oldValue,
      oldValue: newValue,
    });
  } else if (op.action === "deleteWord") {
    const { pid, wid, word, oldOrder, newOrder } = op.payload;
    return createOperation("addWord", {
      pid,
      wid,
      word,
      oldOrder: newOrder,
      newOrder: oldOrder,
    });
  } else if (op.action === "addWord") {
    const { pid, wid, word, oldOrder, newOrder } = op.payload;
    return createOperation("deleteWord", {
      pid,
      wid,
      word,
      oldOrder: newOrder,
      newOrder: oldOrder,
    });
  } else if (op.action === "addParagraph") {
    const { prevPid, pid, paragraph } = op.payload;
    return createOperation("removeParagraph", {
      prevPid,
      pid,
      paragraph,
    });
  } else if (op.action === "removeParagraph") {
    const { prevPid, pid, paragraph } = op.payload;
    return createOperation("addParagraph", {
      prevPid,
      pid,
      paragraph,
    });
  } else if (op.action === "updateParagraph") {
    const { pid, oldParagraph, paragraph } = op.payload;
    return createOperation("updateParagraph", {
      pid,
      oldParagraph: paragraph,
      paragraph: oldParagraph,
    });
  } else if (op.action === "moveWord") {
    const { originPid, targetPid, originOldOrder, originNewOrder, targetOldOrder, targetNewOrder } =
      op.payload;
    return createOperation("moveWord", {
      originPid,
      targetPid,
      originOldOrder: originNewOrder,
      originNewOrder: originOldOrder,
      targetOldOrder: targetNewOrder,
      targetNewOrder: targetOldOrder,
    });
  }

  return null as unknown as AnyOperation;
};

export const applyOp = (book: Book, op: AnyOperation): AnyOperation => {
  if (op.action === "updateWord") {
    const { pid, wid, oldValue, newValue, userChangeText } = op.payload;

    // 判断文本内容是否有变化
    const textNotChangePids = oldValue.text !== newValue.text ? [] : [pid];

    book.updateWord(pid, wid, newValue, userChangeText, textNotChangePids);
  } else if (op.action === "updateWords") {
    const { pid, oldValue, newValue } = op.payload;

    // 判断文本内容是否有变化
    const oldText = oldValue.reduce((_res, { text }) => _res + text, "");
    const newText = newValue.reduce((_res, { text }) => _res + text, "");
    const textNotChangePids = oldText !== newText ? [] : [pid];

    book.updateWords(pid, newValue, textNotChangePids);
  } else if (op.action === "deleteWord") {
    const { pid, wid, newOrder } = op.payload;
    book.deleteWord(pid, wid, newOrder);
  } else if (op.action === "addWord") {
    const { pid, word, newOrder } = op.payload;
    book.addWord(pid, word, newOrder);
  } else if (op.action === "addParagraph") {
    const { prevPid, pid, paragraph } = op.payload;
    book.addParagraph(prevPid, pid, paragraph);
  } else if (op.action === "removeParagraph") {
    const { pid } = op.payload;
    book.removeParagraph(pid);
  } else if (op.action === "updateParagraph") {
    const { pid, oldParagraph, paragraph } = op.payload;
    // 判断发言人是否有变化
    const userChangePids = oldParagraph.uid !== paragraph.uid ? [pid] : [];

    book.updateParagraph(pid, paragraph, userChangePids);
  } else if (op.action === "moveWord") {
    const { originPid, originNewOrder, targetPid, targetNewOrder } = op.payload;
    book.moveWord(originPid, originNewOrder, targetPid, targetNewOrder);
  }
  return invertOp(op) as AnyOperation;
};
