import { UID } from "@tingwujs/core";
import { SphereContext, SphereController } from "../../base";
import {
  SpeakerSummary,
  DisplaySpeakerSummary,
  SpeakerSummaryStates,
  getSpeakerSummaryInitState,
} from "./speakerSummaryState";

export interface SpeakerSummaryEvents {
  // Events will be added as needed
}

export type RenderSpeakerSomething = (uid: UID, size?: number) => any;

export class SpeakerSummaryController extends SphereController<
  SpeakerSummaryStates,
  SpeakerSummaryEvents
> {
  key = "speakerSummary";

  private defaultRenderSpeakerName: RenderSpeakerSomething | undefined;

  private defaultRenderSpeakerAvatar: RenderSpeakerSomething | undefined;

  private uidsMap: Record<UID, boolean> = {};

  constructor(context: SphereContext) {
    super(context, getSpeakerSummaryInitState());
    this.listen();
  }

  listen() {
    const { tingwuController } = this.context;
    this.uidsMap = tingwuController.getAllUidsMap();
    this.updateDisplaySummaries();

    tingwuController.on("modelValueChange", this.handleParagraphChangeSpecific);
    tingwuController.on("paragraphChangeSpecific", this.handleParagraphChangeSpecific);
  }

  unlisten() {
    const { tingwuController } = this.context;
    tingwuController.off("modelValueChange", this.handleParagraphChangeSpecific);
    tingwuController.off("paragraphChangeSpecific", this.handleParagraphChangeSpecific);
  }

  handleParagraphChangeSpecific = () => {
    const { tingwuController } = this.context;
    this.uidsMap = tingwuController.getAllUidsMap();
    this.updateDisplaySummaries();
  };

  setSummaries(summaries: SpeakerSummary[]) {
    const { tingwuController } = this.context;
    this.setState("summaries", summaries);
    this.uidsMap = tingwuController.getAllUidsMap();
    this.updateDisplaySummaries();
  }

  setUidMapping(uidMapping: Record<UID, UID>) {
    this.setState("uidMapping", uidMapping);
    this.updateDisplaySummaries();
  }

  updateDisplaySummaries() {
    const summaries = this.getState("summaries");
    const uidMapping = this.getState("uidMapping");

    const getUniqueId = (() => {
      let id = 1;
      return () => {
        return id++;
      };
    })();
    this.setState(
      "displaySummaries",
      summaries.map(summary => {
        const uid = uidMapping[summary.uid] ?? summary.uid;
        const isDeleted = !this.uidsMap[uid];
        return {
          ...summary,
          realUid: summary.uid,
          uid,
          isDeleted,
          renderedName: isDeleted ? `未知发言人 ${getUniqueId()}` : "",
        };
      })
    );
  }

  setDefaultRenderSpeakerName(defaultRenderSpeakerName: RenderSpeakerSomething) {
    this.defaultRenderSpeakerName = defaultRenderSpeakerName;
  }

  getDefaultRenderSpeakerName(uid: UID) {
    return this.defaultRenderSpeakerName ? this.defaultRenderSpeakerName(uid) : null;
  }

  setDefaultRenderSpeakerAvatar(defaultRenderSpeakerAvatar: RenderSpeakerSomething) {
    this.defaultRenderSpeakerAvatar = defaultRenderSpeakerAvatar;
  }

  getDefaultRenderSpeakerAvatar(uid: UID, size?: number) {
    return this.defaultRenderSpeakerAvatar ? this.defaultRenderSpeakerAvatar(uid, size) : null;
  }

  renderSpeakerAvatar(summary: DisplaySpeakerSummary, size = 28) {
    const { tingwuController } = this.context;
    try {
      return (
        tingwuController.renderAvatar(summary.uid, size) ||
        this.getDefaultRenderSpeakerAvatar(summary.realUid, size)
      );
    } catch (error) {
      return "";
    }
  }

  renderSpeakerName(summary: DisplaySpeakerSummary) {
    const { tingwuController } = this.context;
    try {
      return (
        summary.renderedName ||
        tingwuController.renderSpeakerName(summary.uid) ||
        this.getDefaultRenderSpeakerName(summary.realUid)
      );
    } catch (error) {
      return "";
    }
  }
}
