"use strict";

const bgmList = [
  { normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" },
  { normal: "music/Fear.mp3", gameover: "music/FearGO.mp3" },
  { normal: "music/Chill.mp3", gameover: "music/ChillGO.mp3" },
];

let currentBGM = new Audio();
let gameOverBGM = new Audio();
currentBGM.loop = true;
gameOverBGM.loop = true;

function pickRandomBGM() {
  const bgm = bgmList[Math.floor(Math.random() * bgmList.length)];
  currentBGM.src = bgm.normal;
  gameOverBGM.src = bgm.gameover;
}

var canvasWidth = 1280;
var canvasHeight = 650;
var c = undefined;
var ctx = undefined;
var gameStarted = false;
var musicMuted = false;

let lastFrameTime = 0;
const frameInterval = 1000 / 80;

var game = {
  level: 1,
  speed: 1,
  gameOver: false,
  frames: 0,
  timer: 0,
};

var keys = {
  up: false,
  down: false,
  left: false,
  right: false,
  fire: false,
};

var playerShipImg = new Image();
playerShipImg.src = "img/Player/pesawat22.png";

var bg0 = new Image();
bg0.src = "img/bg_0.png";

var bg1 = new Image();
bg1.src = "img/bg_1.png";

var bg2 = new Image();
bg2.src = "img/bg_2.png";

var enemy1 = new Image();
enemy1.src = "img/alien_0.png";

var enemyImgArray = [];
enemyImgArray.length = 4;

let audioStarted = false;

window.addEventListener("keydown", () => {
  if (!audioStarted) {
    currentBGM.play();
    audioStarted = true;
  }
});

for (var i = 0; i < enemyImgArray.length; i++) {
  enemyImgArray[i] = new Image();
  enemyImgArray[i].src = "img/alien_" + [i] + ".png";
}

var missilesArray = [];
var enemyShipArray = [];

var laser = document.createElement("audio");
laser.src = "music/laser2.mp3";

var explosion_enemy = document.createElement("audio");
explosion_enemy.src = "music/explosion-small.mp3";

var planetImages = [];
for (let i = 1; i <= 4; i++) {
  let img = new Image();
  img.src = `img/SpritesPlanet/planet_${i}.png`;
  planetImages.push(img);
}

window.onload = function () {
  init();
};

function init() {
  c = document.getElementById("canvas");
  ctx = c.getContext("2d");

  document.addEventListener("keydown", keyDownPressed, false);
  document.addEventListener("keyup", keyUpPressed, false);

  gameStarted = true;
  pickRandomBGM();
  currentBGM.volume = 1;
  currentBGM.play();

  requestAnimationFrame(gameLoop);
}

function gameLoop(timestamp) {
  if (!gameStarted) return;

  if (game.gameOver) {
    drawGameOver();
    return;
  }

  if (timestamp - lastFrameTime >= frameInterval) {
    lastFrameTime = timestamp;

    clearGame();
    updateGame();
    drawGame();
  }

  requestAnimationFrame(gameLoop);
}

function keyDownPressed(e) {
  if (e.keyCode == 87 || e.keyCode == 38) {
    keys.up = true;
  } else if (e.keyCode == 83 || e.keyCode == 40) {
    keys.down = true;
  }

  if (e.keyCode == 65 || e.keyCode == 37) {
    keys.left = true;
  }

  if (e.keyCode == 68 || e.keyCode == 39) {
    keys.right = true;
  }

  if (e.keyCode == 32) {
    keys.fire = true;
    missilesArray.push(
      new LaserBullet(player1.x + player1.width, player1.y + player1.height / 2)
    );

    laser.currentTime = 0;
    laser.play();
    laser.volume = 0.4;
  }
}

function keyUpPressed(e) {
  if (e.keyCode == 87 || e.keyCode == 38) {
    keys.up = false;
  } else if (e.keyCode == 83 || e.keyCode == 40) {
    keys.down = false;
  }

  if (e.keyCode == 65 || e.keyCode == 37) {
    keys.left = false;
  }

  if (e.keyCode == 68 || e.keyCode == 39) {
    keys.right = false;
  }

  if (e.keyCode == 32) {
    keys.fire = false;
  }
}

function clearGame() {
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
}

function updateGame() {
  addStarField();
  addShips();

  player1.update();

  if (player1.invincible > 0) player1.invincible--;

  spawnPlanet();
  if (currentPlanet) currentPlanet.update();
  game.frames++;
}

function drawGame() {
  if (currentPlanet) currentPlanet.draw();

  player1.draw();

  for (var i = 0; i < enemyShipArray.length; i++) {
    var s = enemyShipArray[i];
    s.draw();
    s.update();

    if (s.x < -200) {
      enemyShipArray.splice(i, 1);
      i--;
      continue;
    }

    if (Tabrakan(player1, s)) {
      if (player1.invincible <= 0) {
        player1.lives--;
        player1.invincible = 60;
        explosion_enemy.play();

        // --- POSISI RESPAWN TENGAH ---
        // Menggunakan tinggi player yang sudah dihitung agar pas tengah
        player1.x = 100;
        player1.y = canvasHeight / 2 - player1.height / 2;
        player1.vx = 0;
        player1.vy = 0;
        game.frames = 0;

        enemyShipArray.splice(i, 1);
        i--;

        if (player1.lives <= 0) {
          game.gameOver = true;
          crossfadeToGameOver();
        }
        continue;
      }
    }
  }

  for (var i = 0; i < missilesArray.length; i++) {
    var m = missilesArray[i];
    m.draw();
    m.update();

    for (var j = 0; j < enemyShipArray.length; j++) {
      var en = enemyShipArray[j];

      if (Tabrakan(m, en)) {
        player1.score += 100;
        explosion_enemy.play();
        missilesArray.splice(i, 1);
        enemyShipArray.splice(j, 1);
      }
    }

    if (m.x > canvasWidth) {
      missilesArray.splice(i, 1);
      i--;
    }
  }

  drawNewText("Score: " + player1.score, 30, 610, "white");
  drawNewText("Player Lives: " + player1.lives, 1100, 610, "white");
}

class PlayerObject {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.width = 100;
    this.height = 64;
    this.image = playerShipImg;

    this.vx = 0;
    this.vy = 0;
    this.acceleration = 0.8;
    this.friction = 0.92;
    this.maxSpeed = 10;

    this.lives = 3;
    this.score = 0;
    this.health = 100;
    this.invincible = 0;

    this.totalFrames = 5;
    this.frameIndex = 2;
    this.spriteWidth = 0;
    this.sourceHeight = 0;
    this.scale = 1.3;

    this.image.onload = () => {
      this.spriteWidth = this.image.width / this.totalFrames;
      this.sourceHeight = this.image.height;
      this.width = this.spriteWidth * this.scale;
      this.height = this.sourceHeight * this.scale;
      this.y = canvasHeight / 2 - this.height / 2;
    };
  }

  draw() {
    ctx.save();

    if (this.invincible > 0 && this.invincible % 4 < 2) {
      ctx.globalAlpha = 0.5;
    }

    if (this.spriteWidth > 0) {
      ctx.drawImage(
        this.image,
        this.frameIndex * this.spriteWidth,
        0,
        this.spriteWidth,
        this.sourceHeight,
        this.x,
        this.y,
        this.width,
        this.height
      );
    } else {
      ctx.fillStyle = "red";
      ctx.fillRect(this.x, this.y, 50, 50);
    }

    ctx.restore();
  }

  update() {
    if (keys.up) {
      this.vy -= this.acceleration;
    }
    if (keys.down) {
      this.vy += this.acceleration;
    }
    if (keys.left) {
      this.vx -= this.acceleration;
    }
    if (keys.right) {
      this.vx += this.acceleration;
    }

    this.vx *= this.friction;
    this.vy *= this.friction;

    this.x += this.vx;
    this.y += this.vy;

    const bleedY = this.height * 0.4;
    const bleedX = this.width * 0.4;

    if (this.y < -bleedY) {
      this.y = -bleedY;
      if (this.vy < 0) this.vy = 0;
    }
    if (this.y > canvasHeight - this.height + bleedY) {
      this.y = canvasHeight - this.height + bleedY;
      if (this.vy > 0) this.vy = 0;
    }

    if (this.x < -bleedX) {
      this.x = -bleedX;
      if (this.vx < 0) this.vx = 0;
    }
    if (this.x > canvasWidth - this.width + bleedX) {
      this.x = canvasWidth - this.width + bleedX;
      if (this.vx > 0) this.vx = 0;
    }

    if (this.vy < -2.5) {
      this.frameIndex = 4;
    } else if (this.vy < -0.5) {
      this.frameIndex = 3;
    } else if (this.vy > 2.5) {
      this.frameIndex = 0;
    } else if (this.vy > 0.5) {
      this.frameIndex = 1;
    } else {
      this.frameIndex = 2;
    }
  }
}

// Inisialisasi awal (Posisi Y akan di-override otomatis saat gambar load)
let player1 = new PlayerObject(100, 300);

function drawNewText(txt, x, y, color) {
  ctx.font = "20px Arial";
  ctx.fillStyle = color;
  ctx.fillText(txt, x, y);
}

class backgroundObj {
  constructor(img, x, y, speed) {
    this.x = x;
    this.y = y;
    this.width = 2000;
    this.height = 1200;
    this.img = img;
    this.speed = speed;
  }
  draw() {
    ctx.save();
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
    ctx.restore();
  }

  update() {
    this.x -= this.speed;

    if (this.x < -2000) {
      this.x = 2000;
    }
  }
}

let background1 = new backgroundObj(bg0, 0, 0, game.speed * 3);
let background1a = new backgroundObj(bg0, 2000, 0, game.speed * 3);

let background2 = new backgroundObj(bg1, 0, 0, game.speed * 2);
let background2a = new backgroundObj(bg1, 2000, 0, game.speed * 2);

let background3 = new backgroundObj(bg2, 0, 0, game.speed * 1);
let background3a = new backgroundObj(bg2, 2000, 0, game.speed * 1);

function addStarField() {
  background3.draw();
  background3.update();
  background3a.draw();
  background3a.update();

  background2.draw();
  background2.update();
  background2a.draw();
  background2a.update();

  background1.draw();
  background1.update();
  background1a.draw();
  background1a.update();
}

class LaserBullet {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.width = 14;
    this.height = 4;
    this.speed = 16;
  }

  draw() {
    let g = ctx.createLinearGradient(
      this.x,
      this.y,
      this.x + this.width,
      this.y
    );
    g.addColorStop(0, "#00e1ff");
    g.addColorStop(0.5, "#ffffff");
    g.addColorStop(1, "#00e1ff");
    ctx.fillStyle = g;
    ctx.shadowColor = "#00ffff";
    ctx.shadowBlur = 15;
    ctx.fillRect(this.x, this.y, this.width, this.height);
    ctx.shadowBlur = 0;
  }

  update() {
    this.x += this.speed;
  }
}

class EnemyObj {
  constructor(x, y, speed, img) {
    this.x = x;
    this.y = y;
    this.width = 170;
    this.height = 105;
    this.image = img;
    this.speed = speed;
    this.health = 100;
    this.damage = 10;
  }
  draw() {
    ctx.save();
    ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
    ctx.restore();
  }

  update() {
    this.x -= this.speed;
  }
}

let enemy = new EnemyObj(800, 200, 12, enemyImgArray[0]);

class Planet {
  constructor(img) {
    this.image = img;
    this.width = 160;
    this.height = 160;
    this.x = canvasWidth + 50;
    this.y = Math.random() * 300 + 50;
    this.speed = 1.2;
    this.active = true;
  }

  draw() {
    ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
  }

  update() {
    this.x -= this.speed;
    if (this.x < -this.width) {
      this.active = false;
    }
  }
}

let currentPlanet = null;

function spawnPlanet() {
  if (currentPlanet == null || currentPlanet.active === false) {
    let randomImg =
      planetImages[Math.floor(Math.random() * planetImages.length)];
    currentPlanet = new Planet(randomImg);
  }
}

function addShips() {
  if (game.frames > 200) {
    if (game.frames % 150 == 0) {
      var randomY = Math.floor(Math.random() * 500) + 20;
      var randomSpeed = Math.floor(Math.random() * 10) + 1;
      var randomShip = Math.floor(Math.random() * enemyImgArray.length);
      enemyShipArray.push(
        new EnemyObj(1300, randomY, randomSpeed, enemyImgArray[randomShip])
      );
    }
  }
}

function Tabrakan(o, p) {
  if (
    o.x + o.width > p.x &&
    o.x < p.x + p.width &&
    o.y + o.height > p.y &&
    o.y < p.y + p.height
  ) {
    return true;
  }
  return false;
}

function drawGameOver() {
  ctx.fillStyle = "rgba(0,0,0,0.7)";
  ctx.fillRect(0, 0, canvasWidth, canvasHeight);

  ctx.font = "80px Arial";
  ctx.fillStyle = "red";
  ctx.textAlign = "center";
  ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 50);

  ctx.font = "40px Arial";
  ctx.fillStyle = "white";
  ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 30);
}

function crossfadeToGameOver() {
  let fadeSpeed = 0.02;

  gameOverBGM.volume = 0;
  gameOverBGM.play();

  let fadeInterval = setInterval(() => {
    currentBGM.volume -= fadeSpeed;
    if (currentBGM.volume < 0) currentBGM.volume = 0;

    gameOverBGM.volume += fadeSpeed;
    if (gameOverBGM.volume > 1) gameOverBGM.volume = 1;

    if (currentBGM.volume === 0) {
      currentBGM.pause();
      clearInterval(fadeInterval);
    }
  }, 1000 / 30);
}
