import { D, I } from "./engine/public.ts";
import { AlignX, AlignY, Point } from "./engine/datatypes.ts";
import { FG_BOLD } from "./colors.ts";
import { withCamera } from "./layout.ts";
import { VNScene, VNSceneMessage, VNScenePart } from "./vnscene.ts";

const WIDTH = 384;
const HEIGHT = 384;

export class VNModal {
  #scene: VNScene | null;
  #nextIndex = 0;
  #cathexis: SceneCathexis | null;

  constructor() {
    this.#scene = null;
    this.#nextIndex = 0;
    this.#cathexis = null;
  }

  get blocksHud(): boolean {
    return true;
  }

  get isShown(): boolean {
    return this.#scene != null;
  }

  play(scene: VNScene) {
    this.#scene = scene;
    this.#nextIndex = 0;
    this.#cathexis = null;

    this.#fixCathexis();
  }

  #fixCathexis() {
    while (true) {
      if (this.#cathexis?.isDone()) {
        this.#cathexis = null;
      }
      if (this.#cathexis != null) {
        return;
      }

      if (this.#scene == null) {
        return;
      }
      if (this.#cathexis == null) {
        let ix = this.#nextIndex;
        if (ix < this.#scene?.length) {
          this.#cathexis = createCathexis(this.#scene[ix]);
          this.#nextIndex += 1;
        } else {
          this.#scene = null;
        }
      }
    }
  }

  update() {
    this.#fixCathexis();
    withCamera("FullscreenPopover", () => this.#update());
  }

  draw() {
    withCamera("FullscreenPopover", () => this.#draw());
  }

  #update() {
    this.#cathexis?.update();
  }

  #draw() {
    this.#cathexis?.draw();
  }
}

interface SceneCathexis {
  isDone(): boolean;
  update(): void;
  draw(): void;
}

function createCathexis(part: VNScenePart): SceneCathexis {
  switch (part.type) {
    case "message":
      return new SceneMessageCathexis(part);
  }
}

class SceneMessageCathexis {
  #message: VNSceneMessage;
  #done: boolean;
  #gotOneFrame: boolean;

  constructor(message: VNSceneMessage) {
    this.#message = message;
    this.#done = false;
    this.#gotOneFrame = false;
  }

  isDone() {
    return this.#done;
  }

  update() {
    let firstFrame = !this.#gotOneFrame;
    this.#gotOneFrame = true;

    // TODO: SFX
    if (!firstFrame && I.isAnythingPressed()) {
      this.#done = true;
    }
  }

  draw() {
    D.drawText(this.#message.text, new Point(WIDTH / 2, HEIGHT / 2), FG_BOLD, {
      alignX: AlignX.Center,
      alignY: AlignY.Middle,
      forceWidth: WIDTH,
    });
  }
}

let active: VNModal = new VNModal();
export function getVNModal() {
  return active;
}