import './style.css';
import { loadAssets } from './assets';
import { Input } from './input';
import { Game } from './game';
import { VIEW, type RoomId } from './level';

const canvas = document.getElementById('game') as HTMLCanvasElement;

// crisp on high-DPI screens: scale the backing store, draw in logical units
const DPR = Math.min(2, window.devicePixelRatio || 1);
canvas.width = VIEW.w * DPR;
canvas.height = VIEW.h * DPR;
const ctx = canvas.getContext('2d')!;
ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';

function drawLoading(t: number): void {
  ctx.fillStyle = '#070a14';
  ctx.fillRect(0, 0, VIEW.w, VIEW.h);
  ctx.fillStyle = 'rgba(170,210,235,0.8)';
  ctx.font = '15px Georgia, serif';
  ctx.textAlign = 'center';
  ctx.fillText('waking the observatory…', VIEW.w / 2, VIEW.h / 2 - 18);
  ctx.strokeStyle = 'rgba(170,210,235,0.4)';
  ctx.strokeRect(VIEW.w / 2 - 90, VIEW.h / 2, 180, 8);
  ctx.fillRect(VIEW.w / 2 - 88, VIEW.h / 2 + 2, 176 * t, 4);
}
drawLoading(0);

const input = new Input();
input.bindButton(document.getElementById('t-left')!, 'left');
input.bindButton(document.getElementById('t-right')!, 'right');
input.bindButton(document.getElementById('t-jump')!, 'jump');
input.bindButton(document.getElementById('t-attack')!, 'attack');

const assets = await loadAssets((done, total) => drawLoading(done / total));
const game = new Game(assets, input);

// taps on the canvas: RESET SAVE button, else "any key" (start / continue)
canvas.addEventListener('pointerdown', (e) => {
  const r = canvas.getBoundingClientRect();
  const x = ((e.clientX - r.left) / r.width) * VIEW.w;
  const y = ((e.clientY - r.top) / r.height) * VIEW.h;
  if (!game.handleTap(x, y)) input.anyKeyThisFrame = true;
});

// --- e2e / debug hook -------------------------------------------------------
declare global {
  interface Window {
    __game?: {
      readonly phase: string;
      readonly room: RoomId;
      readonly hasAbility: boolean;
      readonly hp: number;
      readonly bossHp: number | null;
      teleport: (room: RoomId, x?: number, y?: number) => void;
      state: () => ReturnType<Game['debugState']>;
    };
  }
}

window.__game = {
  get phase() { return game.debugState().phase; },
  get room() { return game.currentRoom; },
  get hasAbility() { return game.gripTaken; },
  get hp() { return game.player.hearts; },
  get bossHp() { return game.debugState().bossHp; },
  teleport: (room, x?, y?) => game.debugTeleport(room, x, y),
  state: () => game.debugState(),
};

// --- fixed-timestep loop ----------------------------------------------------
const STEP = 1 / 120;
let last = performance.now();
let acc = 0;
function frame(now: number): void {
  const dt = Math.min(0.05, (now - last) / 1000);
  last = now;
  acc += dt;
  while (acc >= STEP) {
    game.update(STEP);
    acc -= STEP;
  }
  game.draw(ctx);
  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
