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

export class VoiceWordController extends AbstractCmdController {
  playingVoicePid: PID | undefined;

  playingVoiceWord: Word | undefined;

  isEnablePlayingVoice = false;

  startPlayingVoiceWord() {
    this.isEnablePlayingVoice = true;
    this.controller.emit("blurCurrentTextEditor", {});
    this.controller.emit("playingVoiceWordEnableChange", {
      enable: true,
    });
  }

  endPlayingVoiceWord() {
    this.isEnablePlayingVoice = false;
    this.controller.emit("playingVoiceWordEnableChange", {
      enable: false,
    });
  }

  getIsEnablePlayingVoice() {
    return this.isEnablePlayingVoice;
  }

  setPlayingVoiceWord(
    pid: PID,
    word: Word | undefined,
    forceDisplay = false,
    isPlaying = true,
    seekWithExtContent = false
  ) {
    const { playingVoicePid } = this;

    this.playingVoicePid = pid;
    this.playingVoiceWord = word;

    if (playingVoicePid && playingVoicePid !== pid) {
      this.controller.emit("playingVoiceWordChange", {
        pid: playingVoicePid,
        word: undefined,
      });
    }

    this.controller.emit("playingVoiceWordChange", {
      pid,
      word,
      forceDisplay,
      seekWithExtContent,
      isPlaying,
    });
  }

  getPlayingPidAndWord(): [PID | undefined, Word | undefined] {
    return [this.playingVoicePid, this.playingVoiceWord];
  }

  getPlayingWord(pid: PID) {
    if (this.playingVoicePid === pid) {
      return this.playingVoiceWord;
    }
    return undefined;
  }

  setPlayingVoiceWordByTime(
    timestamp: number,
    forceDisplay = false,
    isPlaying = true,
    seekWithExtContent = false
  ) {
    const [pid, word] = this.controller.getLastWordByTime(timestamp) || [];
    if (pid && word) {
      this.setPlayingVoiceWord(pid, word, forceDisplay, isPlaying, seekWithExtContent);
    }
  }

  getNextSentencesByTime(timestamp: number): Word[] {
    const [allWords, pos, words] = this.controller.getMatchedWordsByTime(timestamp);
    const [, lastWord] = words.length > 0 ? words[words.length - 1] : allWords[pos];

    const { length } = allWords;
    let foundSentenceId;

    const sentences: Word[] = [];
    for (let i = 0; i < length; i++) {
      const [, word] = allWords[i];
      if (!foundSentenceId && Number(word.sentenceId) > Number(lastWord.sentenceId)) {
        foundSentenceId = word.sentenceId;
      }

      if (foundSentenceId && word.sentenceId === foundSentenceId) {
        sentences.push(word);
      }
    }
    return sentences;
  }

  getPrevSentencesByTime(timestamp: number): Word[] {
    const [allWords, pos, words] = this.controller.getMatchedWordsByTime(timestamp);
    const [, firstWord] = words.length > 0 ? words[0] : allWords[pos];

    const { length } = allWords;
    let foundSentenceId;

    const sentences: Word[] = [];
    for (let i = length - 1; i >= 0; i--) {
      const [, word] = allWords[i];
      if (!foundSentenceId && Number(word.sentenceId) < Number(firstWord.sentenceId)) {
        foundSentenceId = word.sentenceId;
      }

      if (foundSentenceId && word.sentenceId === foundSentenceId) {
        sentences.unshift(word);
      }
    }
    return sentences;
  }

  clearPlayingVoiceWord() {
    const { playingVoicePid } = this;
    this.reset();
    if (playingVoicePid) {
      this.controller.emit("playingVoiceWordChange", {
        pid: playingVoicePid,
        word: undefined,
      });
    }
  }

  reset() {
    this.playingVoicePid = undefined;
    this.playingVoiceWord = undefined;
  }
}
