import { PlayerC } from "./PlayerC";
import * as TWEEN from "@tweenjs/tween.js";
import { GameLoop } from "../core/GameLoop";
import {
  images
} from "../resources/images/images";

// Onboarding/invasion pacing.
const MOVE_TO_HURRY_S = 5; // after the player starts moving, wait this long…
const HURRY_DURATION_S = 2.5; // …then show "HURRY UP" for this long, then the invasion bar
const INVASION_DURATION_S = 60; // the invasion countdown drains over this many seconds
const LOW_FRACTION = 0.25; // below this the bar turns red
const HALF_FRACTION = 0.5; // at/below this the zombie icon grows + shakes
const DEATH_FLY_DELAY_MS = 1000; // pause after death before the zombie icon flies to center

// The onboarding → invasion → death state machine.
enum Phase {
  WaitMove,
  Moving,
  Hurry,
  Invasion,
  Dead,
}

/**
 * The screen-space HUD (HTML overlay): an onboarding flow ("DRAG TO MOVE", then
 * "HURRY UP" → invasion countdown — both inside the invasion container, since one
 * replaces the other), wood/metal counters and a weapon panel. When the invasion
 * timer runs out the player dies and a restart end-card flies in. The wood
 * panel/count carry stable ids so LootC can fly loot into them.
 *
 * Markup classes follow the BEM scheme defined in css/ui.scss: blocks are
 * `.hud-<block>`, children `__element`, state `--modifier`.
 */
export class HudC {
  private static phase = Phase.WaitMove;
  private static timer = 0; // seconds spent in the current phase
  private static remaining = INVASION_DURATION_S;

  private static root: HTMLElement | null = null;
  private static tutorial: HTMLElement | null = null;
  private static invasion: HTMLElement | null = null;
  private static invasionFill: HTMLElement | null = null;
  private static invasionHead: HTMLElement | null = null;
  private static invasionHeadWrap: HTMLElement | null = null; // rides the fill's edge
  private static tweens = new TWEEN.Group();
  private static buttonTween: TWEEN.Tween<{ x: number; y: number }> | null = null;
  static init() {
    const hud = document.createElement("div");
    hud.id = "hud";
    hud.innerHTML = this.markup();
    document.body.appendChild(hud);
    this.root = hud;

    this.tutorial = hud.querySelector(".hud-tutorial");
    this.invasion = hud.querySelector(".hud-invasion");
    this.invasionFill = hud.querySelector(".hud-invasion__fill");
    this.invasionHead = hud.querySelector(".hud-invasion__head");
    this.invasionHeadWrap = hud.querySelector(".hud-invasion__head-wrap");

    // Start with the "DRAG TO MOVE" hint up and the invasion container hidden.
    // Pre-arm the hurry phase while hidden so revealing it later shows only
    // "HURRY UP" (never a flash of the bar before it).
    this.showTutorial("DRAG TO MOVE");
    this.invasion?.classList.add("hud-invasion--hidden", "hud-invasion--hurry-phase");

    GameLoop.register((delta: number) => {
      this.tick(delta);
      this.tweens.update();
    });
  }

  // Whole HUD as one HTML string — simpler than building each node by hand.
  // "HURRY UP" lives inside the invasion container: it shows first, then the bar
  // takes its place (toggled by the .hud-invasion--hurry-phase modifier).
  private static markup(): string {
    return `
      <div class="hud-tutorial"></div>

      <div class="hud-invasion">
        <div class="hud-invasion__hurry">HURRY UP!</div>
        <div class="hud-invasion__title">ZOMBIE INVASION</div>
        <div class="hud-invasion__row">
          <div class="hud-invasion__bar">
            <div class="hud-invasion__track"><div class="hud-invasion__fill"></div></div>
            <div class="hud-invasion__head-wrap"><img class="hud-invasion__head" src="${images.zombieHeadUrl}" /></div>
          </div>
        </div>
      </div>

      <div class="hud-resources">
        <div id="wood-ui" class="hud-resources__panel" style="background-image:url(${images.woodPanelUrl})">
          <div id="wood-count" class="hud-resources__count">0</div>
        </div>
        <div class="hud-resources__panel" style="background-image:url(${images.metalPanelUrl})">
          <div class="hud-resources__count">0</div>
        </div>
      </div>

      <div class="hud-weapon" style="background-image:url(${images.toolPanelUrl})">
        <img class="hud-weapon__icon" src="${images.toolIconUrl}" />
        <div class="hud-weapon__lvl">LVL 0</div>
      </div>
    `;
  }

  private static showTutorial(text: string) {
    if (!this.tutorial) return;
    this.tutorial.textContent = text;
    this.tutorial.classList.add("hud-tutorial--show");
  }
  private static hideTutorial() {
    this.tutorial?.classList.remove("hud-tutorial--show");
  }

  // Onboarding → invasion → death.
  private static tick(delta: number) {
    switch (this.phase) {
      case Phase.WaitMove:
        // Wait until the player drags to move, then drop the hint.
        if (PlayerC.isMoving()) {
          this.hideTutorial();
          this.phase = Phase.Moving;
          this.timer = 0;
        }
        break;

      case Phase.Moving:
        // A few seconds into play, show "HURRY UP" inside the invasion container.
        this.timer += delta;
        if (this.timer >= MOVE_TO_HURRY_S) {
          // --hurry-phase was pre-set in init → fade the container in showing
          // only HURRY UP.
          this.invasion?.classList.remove("hud-invasion--hidden");
          this.phase = Phase.Hurry;
          this.timer = 0;
        }
        break;

      case Phase.Hurry:
        // After the nudge, swap "HURRY UP" out for the countdown bar (same box).
        this.timer += delta;
        if (this.timer >= HURRY_DURATION_S) {
          this.invasion?.classList.remove("hud-invasion--hurry-phase");
          this.phase = Phase.Invasion;
          this.remaining = INVASION_DURATION_S;
        }
        break;

      case Phase.Invasion: {
        this.remaining = Math.max(0, this.remaining - delta);
        const frac = this.remaining / INVASION_DURATION_S; // time LEFT (1 → 0)
        const progress = 1 - frac;                         // invasion FILLS as time elapses (0 → 1)
        if (this.invasionFill) {
          this.invasionFill.style.width = `${progress * 100}%`;
          this.invasionFill.classList.toggle("hud-invasion__fill--low", frac <= LOW_FRACTION);
        }
        // The zombie icon rides the filling edge, advancing as the bar fills up.
        if (this.invasionHeadWrap)
          this.invasionHeadWrap.style.left = `${progress * 100}%`;
        // Half time left: grow + shake. Red zone (low): shake harder + bigger.
        this.invasionHead?.classList.toggle("hud-invasion__head--alert", frac <= HALF_FRACTION);
        this.invasionHead?.classList.toggle("hud-invasion__head--alert-strong", frac <= LOW_FRACTION);
        if (this.remaining <= 0) {
          PlayerC.die();
          this.onDeath();
          this.phase = Phase.Dead;
        }
        break;
      }

      case Phase.Dead:
        break;
    }
  }

  // End-card: the zombie icon flies from the bar to screen center while growing,
  // then a restart button fades in beneath it.
  private static onDeath() {
    if (!this.root) return;

    // Where the small zombie icon sits now (fly start), and the screen center (end).
    const r = this.invasionHead?.getBoundingClientRect();
    const sx = r ? r.left + r.width / 2 : window.innerWidth / 2;
    const sy = r ? r.top + r.height / 2 : 0;
    const cx = window.innerWidth / 2;
    const cy = window.innerHeight / 2;

    this.invasion?.classList.add("hud-invasion--hidden"); // hide the bar + its small icon

    const card = document.createElement("div");
    card.className = "hud-endcard";
    card.innerHTML = `<img class="hud-endcard__zombie" src="${images.zombieHeadUrl}" />`;
    this.root.appendChild(card);

    const zombie = card.querySelector(".hud-endcard__zombie") as HTMLElement;

    // Start the icon small, at the bar's position; then transition to centered
    // full size (CSS animates the transform; the button fades in near the end).
    zombie.style.transform = `translate(${sx - cx}px, ${sy - cy}px) scale(0.35)`;
    void zombie.offsetWidth; // force reflow so the next change animates
    // Hold for a beat (the death animation plays), then fly the icon to center.
    setTimeout(() => {
      zombie.style.transform = "translate(0, 0) scale(1)";
      card.classList.add("hud-endcard--show");

      const btn = document.querySelector(".sudHolder_right") as HTMLElement;
      if (btn) {
        const startRect = btn.getBoundingClientRect();
        btn.style.position = "fixed";
        btn.style.zIndex = "20";
        btn.style.width = "auto";
        btn.style.left = `${startRect.left}px`;
        btn.style.top = `${startRect.top}px`;
        btn.style.transform = "none";

        // Target = centered just under where the zombie ENDS UP (screen center),
        // using its final CSS height. Reading its live rect here would catch it
        // mid-flight (still small / off-center) and put the button in the wrong spot.
        const zh = parseFloat(getComputedStyle(zombie).height) || 0;
        const targetX = cx - btn.offsetWidth / 2;
        const targetY = cy + zh / 2 + 16;

        this.buttonTween?.stop();
        const state = { x: startRect.left, y: startRect.top };
        this.buttonTween = new TWEEN.Tween(state, this.tweens)
          .to({ x: targetX, y: targetY }, 800)
          .delay(150)
          .easing(TWEEN.Easing.Quadratic.Out)
          .onUpdate(({ x, y }) => {
            btn.style.left = `${x}px`;
            btn.style.top = `${y}px`;
          })
          .start();
      }
    }, DEATH_FLY_DELAY_MS);
  }
}
