import type { BookEventMap } from "../model/book";
import { cloneDeep, mergeWith, uniq, isArray, assign } from "lodash-es";

const formatParagraphChangeSpecificEvent = (event: BookEventMap["paragraphChangeSpecific"]) => {
  const newEvent = cloneDeep(event);
  newEvent.updateParagraphPids = newEvent.updateParagraphPids.filter(pid => {
    return newEvent.addParagraphPids.indexOf(pid) === -1;
  });
  newEvent.updateParagraphPids = newEvent.updateParagraphPids.filter(pid => {
    return newEvent.removeParagraphPids.indexOf(pid) === -1;
  });
  return newEvent;
};

export const createParagraphChangeSpecificHandler = (
  callback: (args: BookEventMap["paragraphChangeSpecific"]) => void
) => {
  function genEmptyHolder() {
    return {
      addParagraphPids: [],
      removeParagraphPids: [],
      updateParagraphPids: [],
      removeParagraphs: {},
    };
  }

  let holder: BookEventMap["paragraphChangeSpecific"] = genEmptyHolder();
  let timer: ReturnType<typeof setTimeout>;

  return (args: BookEventMap["paragraphChangeSpecific"]) => {
    if (args.addParagraphPids.length > 0) {
      args.addParagraphPids.forEach(pid => {
        holder.removeParagraphPids = holder.removeParagraphPids.filter(p => p !== pid);
        if (holder.removeParagraphs) {
          delete holder.removeParagraphs[pid];
        }
      });
    }
    mergeWith(holder, args, (a, b) => {
      if (isArray(a)) {
        return uniq(a.concat(b));
      } else {
        assign({}, a, b);
      }
    });

    clearTimeout(timer);
    timer = setTimeout(() => {
      callback(formatParagraphChangeSpecificEvent(holder));
      holder = genEmptyHolder();
    }, 0);
  };
};
