import "./style.css";

import * as logo from "./logo";
import * as welcome from "./welcome";
import * as jugando from "./jugando";
import { Assets, loadAssets } from "./assets";
import { loadSprite, Sprite } from "./sprite";
import { drawText } from "./utils";

export type State = logo.State | welcome.State | jugando.State;

export type Juego<T extends State> = {
  canvas: HTMLCanvasElement;
  ctx: CanvasRenderingContext2D;
  assets: Assets;
  sprites: {
    [key in
      | "botonSiguiente"
      | "botonComenzar"
      | "botonCompartirPerdiste"
      | "botonCompartirFelicitaciones"
      | "instagram"
      | "twitter"
      | "facebook"
      | "logoFPGFDTBlanco"
      | "logoSalvaLaCostaneraGrande"
      | "logoSalvaLaCostaneraCostado"
      | "instrucciones1"
      | "instrucciones2"
      | "instrucciones3"
      | "placaPerdiste"
      | "placaFelicitaciones"
      | "dialogoFirma"
      | "flecha"
      | "jugadorx"
      | "jugadorxPresentando"
      | "baldosa"
      | "larreta"
      | "millonarioMalo"
      | "semilla"
      | "arbol1"
      | "arbol2"
      | "ciudadanx1"
      | "ciudadanx2"
      | "ciudadanx3"]: Sprite;
  };
  mouse: { x: number; y: number; down: boolean };
  touches: TouchList | null;
  keyboard: { keys: { [key: string]: boolean } };
  state: T;
};

function needsRotation(juego: Juego<any>): boolean {
  return juego.canvas.width < juego.canvas.height;
}

function update(juego: Juego<any>, dt: number) {
  if (needsRotation(juego)) return;
  switch (juego.state.current) {
    case "logo":
      logo.update(juego, dt);
      break;
    case "welcome":
      welcome.update(juego, dt);
      break;
    case "jugando":
      jugando.update(juego, dt);
      break;
  }
}

function draw(juego: Juego<any>, timestamp: number) {
  const { width, height } = juego.canvas;

  juego.ctx.imageSmoothingEnabled = false;

  juego.ctx.fillStyle = "white";
  juego.ctx.fillRect(0, 0, width, height);
  juego.ctx.fillStyle = "black";

  if (needsRotation(juego)) {
    drawText(
      juego,
      "¡Por favor rotá el dispositivo!",
      { x: juego.canvas.width / 2, y: juego.canvas.height / 2 },
      { align: "center", maxWidth: juego.canvas.width }
    );
    return;
  }

  switch (juego.state.current) {
    case "logo":
      logo.draw(juego, timestamp);
      break;
    case "welcome":
      welcome.draw(juego, timestamp);
      break;
    case "jugando":
      jugando.draw(juego, timestamp);
      break;
  }
}

function resizeCanvas(canvas: HTMLCanvasElement) {
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
}

function touchListener(juego: Juego<any>, event: TouchEvent) {
  juego.touches = event.touches;
}

async function initJuego() {
  const canvas = document.querySelector<HTMLCanvasElement>("#juego")!;
  const ctx = canvas.getContext("2d", {
    alpha: false,
    desynchronized: true,
  })!;

  window.addEventListener("resize", () => resizeCanvas(canvas), false);
  resizeCanvas(canvas);

  const assets = await loadAssets();

  const sprites = {
    botonComenzar: loadSprite(assets.botonComenzar, {
      height: (juego) => juego.canvas.height / 8,
    }),
    botonSiguiente: loadSprite(assets.botonSiguiente, {
      height: (juego) => juego.canvas.height / 8,
    }),
    botonCompartirPerdiste: loadSprite(assets.botonCompartirPerdiste, {
      height: (juego) => juego.canvas.height / 8,
    }),
    botonCompartirFelicitaciones: loadSprite(
      assets.botonCompartirFelicitaciones,
      {
        height: (juego) => juego.canvas.height / 8,
      }
    ),
    instagram: loadSprite(assets.instagram, {
      height: (juego) => juego.canvas.height * 0.1,
    }),
    facebook: loadSprite(assets.facebook, {
      height: (juego) => juego.canvas.height * 0.1,
    }),
    twitter: loadSprite(assets.twitter, {
      height: (juego) => juego.canvas.height * 0.1,
    }),
    logoFPGFDTBlanco: loadSprite(assets.logoFPGFDTBlanco, {
      height: (juego) => juego.canvas.height / 6,
    }),
    logoSalvaLaCostaneraGrande: loadSprite(assets.logoSalvaLaCostanera, {
      height: (juego) => juego.canvas.height * 0.45,
    }),
    logoSalvaLaCostaneraCostado: loadSprite(
      assets.logoSalvaLaCostaneraCostado,
      { height: (juego) => juego.canvas.height / 4 }
    ),
    instrucciones1: loadSprite(assets.instrucciones1, {
      width: (juego) => juego.canvas.width * 0.5,
    }),
    instrucciones2: loadSprite(assets.instrucciones2, {
      width: (juego) => juego.canvas.width * 0.5,
    }),
    instrucciones3: loadSprite(assets.instrucciones3, {
      width: (juego) => juego.canvas.width * 0.5,
    }),
    placaPerdiste: loadSprite(assets.placaPerdiste, {
      height: (juego) => juego.canvas.height * 0.6,
    }),
    placaFelicitaciones: loadSprite(assets.placaFelicitaciones, {
      height: (juego) => juego.canvas.height * 0.6,
    }),
    dialogoFirma: loadSprite(assets.dialogoFirma, {
      height: (juego) => juego.canvas.height / 8,
    }),
    flecha: loadSprite(assets.flecha, {
      height: (juego) => juego.canvas.height / 6,
    }),
    jugadorx: loadSprite(
      assets.jugadorx,
      { height: (juego) => juego.canvas.height / 4 },
      {
        width: 56,
        height: 94,
      }
    ),
    jugadorxPresentando: loadSprite(assets.jugadorxPresentando, {
      height: (juego) => juego.canvas.height * 0.8,
    }),
    baldosa: loadSprite(assets.baldosa, {
      height: (juego) => juego.canvas.height * 0.2,
    }),
    larreta: loadSprite(
      assets.larreta,
      { height: (juego) => juego.canvas.height / 4 },
      {
        width: 83,
        height: 131,
      }
    ),
    millonarioMalo: loadSprite(
      assets.millonarioMalo,
      { height: (juego) => juego.canvas.height / 4 },
      { width: 50, height: 71 }
    ),
    semilla: loadSprite(assets.semilla, {
      height: (juego) => juego.canvas.height / 8,
    }),
    arbol1: loadSprite(
      assets.arbol1,
      { height: (juego) => juego.canvas.height / 3 },
      {
        width: 72,
        height: 68,
      }
    ),
    arbol2: loadSprite(
      assets.arbol2,
      { height: (juego) => juego.canvas.height / 4 },
      {
        width: 72,
        height: 56,
      }
    ),
    ciudadanx1: loadSprite(
      assets.ciudadanx1,
      {
        height: (juego) => juego.canvas.height / 4,
      },
      { width: 45, height: 88 }
    ),
    ciudadanx2: loadSprite(
      assets.ciudadanx2,
      {
        height: (juego) => juego.canvas.height / 4,
      },
      { width: 45, height: 88 }
    ),
    ciudadanx3: loadSprite(
      assets.ciudadanx3,
      {
        height: (juego) => juego.canvas.height / 4,
      },
      { width: 45, height: 86 }
    ),
  };

  let juego: Juego<logo.State> = {
    canvas,
    ctx,
    assets,
    sprites,
    mouse: { x: 0, y: 0, down: false },
    touches: null,
    keyboard: { keys: {} },
    state: logo.createState(),
  };
  (window as any).juego = juego;
  juego.ctx.imageSmoothingEnabled = false;

  canvas.addEventListener(
    "mousemove",
    (e) => {
      juego.mouse.x = e.clientX;
      juego.mouse.y = e.clientY;
    },
    false
  );
  canvas.addEventListener(
    "mousedown",
    () => {
      juego.mouse.down = true;
    },
    false
  );
  canvas.addEventListener(
    "mouseup",
    () => {
      juego.mouse.down = false;
    },
    false
  );
  window.addEventListener("keydown", (e) => {
    juego.keyboard.keys[e.key] = true;
  });
  window.addEventListener("keyup", (e) => {
    juego.keyboard.keys[e.key] = false;
  });
  window.addEventListener("touchstart", (e) => touchListener(juego, e));
  window.addEventListener("touchend", (e) => touchListener(juego, e));
  window.addEventListener("touchcancel", (e) => touchListener(juego, e));
  window.addEventListener("touchmove", (e) => touchListener(juego, e));

  let lastRender = 0;
  const loop: FrameRequestCallback = (timestamp) => {
    const progress = timestamp - lastRender;

    update(juego, progress);
    draw(juego, timestamp);

    lastRender = timestamp;
    window.requestAnimationFrame(loop);
  };

  window.requestAnimationFrame(loop);

  console.log(
    "%c¡Hola curiosx! Podés ver el código completo en https://gitea.nulo.in/Nulo/salva-la-costanera. ¡Suerte!",
    "color:green;font-size:3rem;font-weight:bold"
  );
}

const fullscreenEl = document.getElementById("full-screen")!;
if ("requestFullscreen" in document.documentElement) {
  fullscreenEl.addEventListener("click", async () => {
    document.documentElement.requestFullscreen &&
      (await document.documentElement.requestFullscreen({
        navigationUI: "hide",
      }));
    await screen.orientation.lock("landscape");
  });
} else {
  fullscreenEl.hidden = true;
}

initJuego();
