import { AnyFun } from "queenjs/typing";
import { EditorModule } from "../../module";
import { Action, HistoryController } from "./HistoryController";
import { get } from "lodash";

export class HistoryCtrl {
  history: HistoryController;
  historyActionDoing = false;
  historyCombine = false;
  safeList = ["layout.size"];

  constructor(protected module: EditorModule, historyTotal = 50) {
    this.history = new HistoryController();
    this.history.state.maxLen = historyTotal;
  }

  record(
    root: any,
    type: Action["type"],
    paths: string[],
    value: any,
    oldValue: any
  ) {
    if (this.historyActionDoing) {
      if (
        type === "set" && 
        !this.safeList.some((str) => paths.slice(0, -1).join(".").includes(str))
      ) {
        const parent = paths.length > 1 ? get(root, paths.slice(0, -1)) : root;
        if (parent instanceof Array) {
          console.warn(
            `操作警告[set:${paths.join(
              "."
            )}],应将数组整体替换赋值,不要操作原数组对象`
          );
        }
      }
      const action = new Action(type, root, paths.join("."), value, oldValue);
      this.history.record(action, { combine: this.historyCombine });
    }
  }

  bindActions(actNames: string[]) {
    const actions: any = this.module.actions;
    actNames.forEach((actName) => {
      const action = actions[actName];
      actions[actName] = this.proxyAction.bind(this, action);
    });
  }

  async proxyAction(action: AnyFun, ...args: any[]) {
    const { history } = this;
    if (this.historyActionDoing) {
      return await action(...args);
    }
    try {
      this.historyActionDoing = true;
      await action(...args);
      history.submit();
    } catch (error) {
      console.error(error);
      history.cacheGroupAction.undo();
      history.cacheGroupAction.actions = [];
    } finally {
      this.historyActionDoing = false;
    }
  }
}
