/* INPUT */
const keys = { w:false, s:false, a:false, d:false };

window.addEventListener("keydown", e => {
  if (e.key === "w") keys.w = true;
  if (e.key === "s") keys.s = true;
  if (e.key === "a") keys.a = true;
  if (e.key === "d") keys.d = true;
  if (e.key === "Escape") togglePauseMenu();
  if (e.key === "v") toggleCameraMode();
});

window.addEventListener("keyup", e => {
  if (e.key === "w") keys.w = false;
  if (e.key === "s") keys.s = false;
  if (e.key === "a") keys.a = false;
  if (e.key === "d") keys.d = false;
});

/* CAMERA */
let chaseCam = true;
let viewOverride = false;
let cameraPitch = 55;

function toggleCameraMode(){ chaseCam = !chaseCam; }
function toggleOverrideMode(){ viewOverride = !viewOverride; }

/* PLAYER */
class Player {
  constructor(lng, lat) {
    this.lng = lng;
    this.lat = lat;

    this.heading = 0;
    this.speed = 0;

    this.maxSpeed = 40;
    this.accel = 20;
    this.brake = 30;
    this.turnRate = 120;
    this.friction = 8;

    this.img = new Image();
    this.img.src = "player.png";
  }

  update(dt) {

    // SMART STEERING
    const speedFactor = Math.min(Math.abs(this.speed) / this.maxSpeed, 1);
    const turn = this.turnRate * (0.3 + speedFactor);

    if (keys.a) this.heading -= turn * dt;
    if (keys.d) this.heading += turn * dt;

    if (keys.w) this.speed += this.accel * dt;
    if (keys.s) this.speed -= this.brake * dt;

    if (this.speed > this.maxSpeed) this.speed = this.maxSpeed;
    if (this.speed < -this.maxSpeed * 0.4) this.speed = -this.maxSpeed * 0.4;

    if (!keys.w && !keys.s) {
      if (this.speed > 0) this.speed -= this.friction * dt;
      if (this.speed < 0) this.speed += this.friction * dt;
      if (Math.abs(this.speed) < 0.1) this.speed = 0;
    }

    const rad = this.heading * Math.PI/180;
    const p = map.project([this.lng, this.lat]);

    const np = {
      x: p.x + Math.cos(rad)*this.speed*dt,
      y: p.y + Math.sin(rad)*this.speed*dt
    };

    const ll = map.unproject(np);
    this.lng = ll.lng;
    this.lat = ll.lat;
  }

  draw(ctx) {
    const pos = map.project([this.lng, this.lat]);
    ctx.drawImage(this.img, pos.x-25, pos.y-25, 50, 50);
  }
}

/* INIT */
let map, player, canvas, ctx;
let lastTime = performance.now();

window.onload = () => {

  map = new maplibregl.Map({
    container:'map',
    style:'./map-style.json',
    center:[173.284, -41.270],
    zoom:17.5,
    pitch:cameraPitch
  });

  // DEBUG (helps with black screen)
  map.on('error', e => console.error("MAP ERROR:", e.error));

  canvas = document.getElementById("game");
  ctx = canvas.getContext("2d");

  resizeCanvas();
  window.addEventListener("resize", resizeCanvas);

  player = new Player(173.284, -41.270);

  initMenu();

  map.on("render", gameLoop);
};

/* LOOP */
function gameLoop() {
  const now = performance.now();
  const dt = (now-lastTime)/1000;
  lastTime = now;

  player.update(dt);

  if (chaseCam) {
    map.setPitch(cameraPitch);
    if (!viewOverride) map.setBearing(player.heading);
  } else {
    map.setPitch(0);
    map.setBearing(0);
  }

  map.setCenter([player.lng, player.lat]);

  ctx.clearRect(0,0,canvas.width,canvas.height);
  player.draw(ctx);
}

/* MENU */
function initMenu(){

  const bind = id => {
    const el = document.getElementById(id);
    el.value = player[id] || cameraPitch;

    el.oninput = e => {
      const v = parseFloat(e.target.value);
      if (id in player) player[id] = v;
      if (id === "zoom") map.setZoom(v);
      if (id === "pitch") cameraPitch = v;
    };
  };

  ["accel","brake","maxSpeed","friction","turnRate","zoom","pitch"].forEach(bind);

  spawnLng.value = player.lng;
  spawnLat.value = player.lat;

  respawn.onclick = () => {
    player.lng = parseFloat(spawnLng.value);
    player.lat = parseFloat(spawnLat.value);
  };

  reset.onclick = () => location.reload();
}

/* HELPERS */
function resizeCanvas(){
  canvas.width = innerWidth;
  canvas.height = innerHeight;
}

function togglePauseMenu(){
  const pm = document.getElementById("pauseMenu");
  pm.style.display = pm.style.display === "block" ? "none" : "block";
}

toggleView.onclick = toggleCameraMode;
toggleOverride.onclick = toggleOverrideMode;
closePause.onclick = togglePauseMenu;