import { Object3D } from "three";
import { UpdateController } from "@24tools/playable_template";
import { ThreeC } from "../ThreeC";
import { PropC } from "./PropC";
import { PropHpBar } from "./PropHpBar";

/** TODO: set false after HP bar position tuning */
const DEBUG_ALWAYS_VISIBLE_HP_BARS = false;

export class PropHpUIC {
  private static inited = false;
  private static overlayLayer: Object3D | null = null;
  private static bars = new Map<PropC, PropHpBar>();

  static init() {
    if (this.inited) return;
    this.inited = true;

    this.hideSceneTemplate();
    this.ensureOverlayLayer();

    UpdateController.Instance.onUpdate.addDelegate((delta) => {
      for (const bar of this.bars.values()) {
        bar.update(delta);
      }
    });
  }

  /** Call after map/scene objects are added so overlay renders last. */
  static bringOverlayToFront() {
    this.ensureOverlayLayer();
    const layer = this.overlayLayer;
    if (!layer) return;

    let parent = layer.parent;
    if (!parent) {
      ThreeC.addToScene(layer);
      parent = layer.parent;
      if (!parent) return;
    }

    parent.remove(layer);
    parent.add(layer);
  }

  static createBar(prop: PropC): PropHpBar | undefined {
    if (!PropHpBar.getPrefab()) {
      console.warn("HP bar prefab not loaded");
      return undefined;
    }
    if (this.bars.has(prop)) return this.bars.get(prop);

    const bar = new PropHpBar(prop, this.getOverlayLayer());
    this.bars.set(prop, bar);

    if (DEBUG_ALWAYS_VISIBLE_HP_BARS) {
      bar.setVisible(true);
    }

    return bar;
  }

  static showFor(props: PropC[]) {
    if (DEBUG_ALWAYS_VISIBLE_HP_BARS) {
      this.showAll();
      return;
    }

    for (const bar of this.bars.values()) {
      bar.setVisible(false);
    }

    for (const prop of props) {
      if (prop.isBroken) continue;
      this.bars.get(prop)?.setVisible(true);
    }
  }

  static hideAll() {
    if (DEBUG_ALWAYS_VISIBLE_HP_BARS) return;

    for (const bar of this.bars.values()) {
      bar.setVisible(false);
    }
  }

  private static showAll() {
    for (const [prop, bar] of this.bars) {
      bar.setVisible(!prop.isBroken);
    }
  }

  static removeBar(prop: PropC) {
    const bar = this.bars.get(prop);
    if (!bar) return;

    bar.destroy();
    this.bars.delete(prop);
  }

  private static hideSceneTemplate() {
    const template = PropHpBar.getPrefab();
    if (!template || !template.parent) return;

    template.visible = false;
    template.removeFromParent();
  }

  private static ensureOverlayLayer() {
    if (!this.overlayLayer) {
      this.overlayLayer = new Object3D();
      this.overlayLayer.name = "prop-hp-overlay";
      this.overlayLayer.frustumCulled = false;
      this.overlayLayer.renderOrder = PropHpBar.OVERLAY_RENDER_ORDER;
      ThreeC.addToScene(this.overlayLayer);
    }
  }

  private static getOverlayLayer() {
    this.ensureOverlayLayer();
    return this.overlayLayer!;
  }
}
