import { AbstractCmdController } from "./abstractCmdController";
import { PID, SC, Word } from "../persist";
import { getWordsBySces } from "../utils";

export interface FixParagraphTranslateTranslate {
  pid: PID;
  translateResult: Word[];
  isTranslating?: boolean;
  isTranslateError?: boolean;
}

export type FixParagraphTranslateMap = Record<PID, FixParagraphTranslateTranslate>;

export interface UnfixParagraphTranslate {
  pid?: PID;
  fixContentTranslate: Word[];
  unfixContentTranslate: string;
}

export enum TranslateMode {
  OriginAndTranslate,
  TranslateOnly,
  Disabled,
}

export class TranslateController extends AbstractCmdController {
  private fixParagraphTranslate: FixParagraphTranslateMap = {};

  private unfixParagraphTranslate: UnfixParagraphTranslate = {
    fixContentTranslate: [],
    unfixContentTranslate: "",
  };

  private translateMode: TranslateMode = TranslateMode.Disabled;

  setTranslateMode(translateMode: TranslateMode) {
    const oldTranslateMode = this.translateMode;
    this.translateMode = translateMode;
    const livingMode = this.controller.getLivingMode();

    if (
      livingMode &&
      oldTranslateMode === TranslateMode.Disabled &&
      translateMode !== TranslateMode.Disabled
    ) {
      // 当开启翻译时，触发一次unfixContentChange，为了能够触发一次翻译
      this.controller.emitUnfixContentChange();
    }
    this.controller.emit("translateModeChange", {
      translateMode,
    });
  }

  getTranslateMode(_pid?: PID) {
    return this.translateMode;
  }

  setTranslating(pid: PID, isTranslating: boolean) {
    const translate = this.fixParagraphTranslate[pid];
    if (translate && translate.isTranslating === isTranslating && !translate.isTranslateError) {
      return;
    }

    if (translate == null) {
      this.fixParagraphTranslate[pid] = {
        translateResult: [],
        pid,
        isTranslating,
        isTranslateError: false,
      };
    } else {
      translate.isTranslating = true;
      translate.isTranslateError = false;
    }

    this.controller.emit("fixParagraphTranslateChange", {
      pid,
      translate: this.fixParagraphTranslate[pid],
    });
  }

  isTranslateError(words: Word[]) {
    return words.map(word => word.text).join("").length === 0;
  }

  //
  // return isSuccessful
  setTranslate(pid: PID, translate: SC[]): boolean {
    return this.setTranslateByWords(pid, getWordsBySces(translate));
  }

  //
  // return isSuccessful
  setTranslateByWords(pid: PID, translate: Word[]): boolean {
    const isHasContent = this.controller.getTextContent(pid);
    const isError = isHasContent && this.isTranslateError(translate);

    if (!this.fixParagraphTranslate[pid]) {
      this.fixParagraphTranslate[pid] = {
        pid,
        translateResult: [],
      };
    }
    this.fixParagraphTranslate[pid].isTranslating = false;
    if (isError) {
      this.fixParagraphTranslate[pid].isTranslateError = true;
    } else {
      this.fixParagraphTranslate[pid].isTranslateError = false;
      this.fixParagraphTranslate[pid].translateResult = translate;
    }
    this.controller.emit("fixParagraphTranslateChange", {
      pid,
      translate: this.fixParagraphTranslate[pid],
    });

    return !isError;
  }

  getTranslate(pid: PID) {
    return this.fixParagraphTranslate[pid];
  }

  setUnfixTranslate(
    pid: PID | undefined,
    unfixContentTranslate: string,
    fixContentTranslate: SC[]
  ) {
    this.setUnfixTranslateByWords(pid, unfixContentTranslate, getWordsBySces(fixContentTranslate));
  }

  setUnfixTranslateByWords(
    pid: PID | undefined,
    unfixContentTranslate: string,
    fixContentTranslate: Word[]
  ) {
    this.unfixParagraphTranslate = {
      pid,
      unfixContentTranslate,
      fixContentTranslate,
    };
    this.controller.emit("unfixParagraphTranslateChange", this.unfixParagraphTranslate);
  }

  getUnfixTranslate() {
    return this.unfixParagraphTranslate;
  }

  setUnfixToFixed(newUnfixPid?: PID) {
    const { pid, fixContentTranslate } = this.getUnfixTranslate();
    if (pid) {
      this.setUnfixTranslate(newUnfixPid, "", []);
      this.setTranslateByWords(pid, fixContentTranslate);
    }
  }

  reset() {
    this.fixParagraphTranslate = {};
    this.unfixParagraphTranslate = {
      fixContentTranslate: [],
      unfixContentTranslate: "",
    };
  }
}
