"use strict";

document.addEventListener("DOMContentLoaded", () => {
  class SnakeGame {
    constructor() {
      this.cvs = document.getElementById("game");
      this.ctx = this.cvs.getContext("2d");
      this.startBtn = document.getElementById("start");
      this.description = document.getElementById("description");
      this.box = 32;

      this.ground = new Image();
      this.ground.src = "img/ground.png";

      this.foodImg = new Image();
      this.foodImg.src = "img/food.png";

      this.sounds = {
        dead: new Audio("audio/dead.mp3"),
        eat: new Audio("audio/eat.mp3"),
        up: new Audio("audio/up.mp3"),
        right: new Audio("audio/right.mp3"),
        left: new Audio("audio/left.mp3"),
        down: new Audio("audio/down.mp3"),
      };

      this.snake = [{ x: 9 * this.box, y: 10 * this.box }];
      this.food = this.getRandomFoodPosition();
      this.score = 0;
      this.direction = null;
      this.game = null;

      document.addEventListener("keydown", (event) =>
        this.handleKeyPress(event)
      );
      this.initControls();
      this.startBtn.addEventListener("click", () => this.startGame());
    }

    getRandomFoodPosition() {
      return {
        x: Math.floor(Math.random() * 17 + 1) * this.box,
        y: Math.floor(Math.random() * 15 + 3) * this.box,
      };
    }

    handleKeyPress(event) {
      const key = event.key.toLowerCase();
      if ((key === "arrowleft" || key === "a") && this.direction !== "RIGHT")
        this.changeDirection("LEFT");
      if ((key === "arrowup" || key === "w") && this.direction !== "DOWN")
        this.changeDirection("UP");
      if ((key === "arrowright" || key === "d") && this.direction !== "LEFT")
        this.changeDirection("RIGHT");
      if ((key === "arrowdown" || key === "s") && this.direction !== "UP")
        this.changeDirection("DOWN");
    }

    initControls() {
      document
        .getElementById("up")
        .addEventListener("click", () => this.changeDirection("UP"));
      document
        .getElementById("down")
        .addEventListener("click", () => this.changeDirection("DOWN"));
      document
        .getElementById("left")
        .addEventListener("click", () => this.changeDirection("LEFT"));
      document
        .getElementById("right")
        .addEventListener("click", () => this.changeDirection("RIGHT"));
    }

    changeDirection(newDirection) {
      this.direction = newDirection;
      this.sounds[newDirection.toLowerCase()].play();
    }

    collision(head, array) {
      return array.some(
        (segment) => segment.x === head.x && segment.y === head.y
      );
    }

    draw() {
      this.ctx.drawImage(this.ground, 0, 0);

      this.snake.forEach((segment, index) => {
        this.ctx.fillStyle = index === 0 ? "green" : "white";
        this.ctx.fillRect(segment.x, segment.y, this.box, this.box);
        this.ctx.strokeStyle = "red";
        this.ctx.strokeRect(segment.x, segment.y, this.box, this.box);
      });

      this.ctx.drawImage(this.foodImg, this.food.x, this.food.y);

      let snakeX = this.snake[0].x;
      let snakeY = this.snake[0].y;

      if (this.direction === "LEFT") snakeX -= this.box;
      if (this.direction === "UP") snakeY -= this.box;
      if (this.direction === "RIGHT") snakeX += this.box;
      if (this.direction === "DOWN") snakeY += this.box;

      if (snakeX === this.food.x && snakeY === this.food.y) {
        this.score++;
        this.sounds.eat.play();
        this.food = this.getRandomFoodPosition();
      } else {
        this.snake.pop();
      }

      let newHead = { x: snakeX, y: snakeY };
      if (
        snakeX < this.box ||
        snakeX > 17 * this.box ||
        snakeY < 3 * this.box ||
        snakeY > 17 * this.box ||
        this.collision(newHead, this.snake)
      ) {
        clearInterval(this.game);
        this.sounds.dead.play();
      }

      this.snake.unshift(newHead);
      this.ctx.fillStyle = "white";
      this.ctx.font = "45px Changa one";
      this.ctx.fillText(this.score, 2 * this.box, 1.6 * this.box);
    }

    startGame() {
      this.description.style.display = "none";
      this.game = setInterval(() => this.draw(), 100);
    }
  }

  new SnakeGame();
});