import { SID } from "../persist";
import { AbstractCmdController } from "./abstractCmdController";

export interface AgendaCheckpoint {
  id: number;
  value: string;
  time?: number;
  endTime?: number;
  extensions?: Array<{
    startTime: number;
    endTime: number;
    sId: number;
  }>;
}

export interface Agenda {
  id: string;
  title: string;
  beginTime: number;
  endTime: number;
  highlightContents: Array<{
    beginTime: number;
    endTime: number;
    sid: SID;
  }>;
}

export class AgendaController extends AbstractCmdController {
  private agendas: Agenda[] = [];

  private activeAgendaIndex: number | undefined;

  private enableActiveAgenda = false;

  private activeAgendaPid: string | undefined;

  getEnableActiveAgenda() {
    return this.enableActiveAgenda;
  }

  setAgendas(agendas: Agenda[]) {
    this.agendas = agendas;
    this.controller.emit("agendasChange", { agendas });
  }

  getAgendas() {
    return this.agendas;
  }

  fromJSON(agendaCheckpoints: AgendaCheckpoint[]) {
    if (!agendaCheckpoints || agendaCheckpoints.length === 0) {
      this.setAgendas([]);
    }

    const agendas: Agenda[] = agendaCheckpoints.map(cp => {
      return {
        id: String(cp.id),
        title: cp.value,
        beginTime: cp.time || 0,
        endTime: cp.endTime || 0,
        highlightContents: (cp.extensions || []).map(ext => {
          return {
            beginTime: ext.startTime,
            endTime: ext.endTime,
            sid: String(ext.sId),
          };
        }),
      };
    });

    this.setAgendas(agendas);
    this.activeAgendaIndex = undefined;
  }
  getActiveAgenda() {
    if (this.activeAgendaIndex == null || !this.agendas) {
      return undefined;
    }
    return this.agendas[this.activeAgendaIndex];
  }

  setActiveAgendaById(id: string) {
    if (!this.agendas) {
      return;
    }
    const { length } = this.agendas;
    for (let i = 0; i < length; i++) {
      const agenda = this.agendas[i];

      if (`${agenda.id}` === `${id}`) {
        if (this.activeAgendaIndex === i) {
          return;
        }
        this.enableActiveAgenda = true;
        this.activeAgendaIndex = i;
        this.controller.emit("activeAgendaChange", {
          agenda: this.agendas[i],
        });
        return;
      }
    }
    this.clearActiveAgenda();
  }

  clearActiveAgenda() {
    this.enableActiveAgenda = false;
    this.activeAgendaIndex = undefined;
    this.activeAgendaPid = undefined;
    this.controller.emit("activeAgendaChange", {
      agenda: undefined,
    });
  }

  getMeetingActiveAgenda() {
    return this.getActiveAgenda();
  }

  setMeetingActiveAgendaById(id?: string) {
    if (!this.agendas) {
      return;
    }
    if (!id) {
      this.clearMeetingActiveAgenda();
      return;
    }
    const { length } = this.agendas;
    for (let i = 0; i < length; i++) {
      const agenda = this.agendas[i];

      if (`${agenda.id}` === `${id}`) {
        if (this.activeAgendaIndex === i) {
          return;
        }
        this.enableActiveAgenda = true;
        this.activeAgendaIndex = i;

        const pids = this.controller.getPids();
        if (agenda.beginTime === 0) {
          this.activeAgendaPid = pids[0];
        } else {
          const pid =
            pids.find(pid => {
              const words = this.controller.getWords(pid);
              return words[words.length - 1].endTime > agenda.beginTime;
            }) || pids[pids.length - 1];
          this.activeAgendaPid = pid;
        }
        this.controller.emit("meetingActiveAgendaChange", { pid: this.activeAgendaPid });
        this.controller.emit("activeAgendaChange", {
          agenda,
        });
        return;
      }
    }
    this.clearMeetingActiveAgenda();
  }

  clearMeetingActiveAgenda() {
    this.clearActiveAgenda();
  }

  setActiveAgendaByTime(timestamp: number) {
    if (!this.agendas) {
      return;
    }
    this.agendas.some(agenda => {
      if (agenda) {
        if (timestamp >= agenda.beginTime && timestamp <= agenda.endTime) {
          this.setActiveAgendaById(agenda.id);
          return true;
        }
      }
      return false;
    });
  }

  getActiveAgendaHighlightSids() {
    if (this.activeAgendaIndex == null || !this.agendas || !this.agendas[this.activeAgendaIndex]) {
      return [];
    }
    return this.agendas[this.activeAgendaIndex].highlightContents.map(c => c.sid);
  }

  getMeetingActiveAgendaPid() {
    return this.activeAgendaPid;
  }

  reset() {
    this.agendas = [];
    this.activeAgendaIndex = undefined;
    this.enableActiveAgenda = false;
    this.activeAgendaPid = undefined;
  }
}
