import { useEffect, useRef } from "react";
import styles from "./GuessPane.module.css";

const tileSize = 15;
const tiles = 40;
const rawSize = tileSize * tiles;

const drawTile = (ctx, x, y, color) => {
  ctx.fillStyle = color;
  ctx.fillRect(x * tileSize, y * tileSize, tileSize, tileSize);
};

const snakeGame = () => {
  const snakeHead = { x: null, y: null, vx: null, vy: null };
  let snakeTail = [];
  const apple = { x: null, y: null };

  const randomApple = () => {
    apple.x = Math.floor(Math.random() * tiles);
    apple.y = Math.floor(Math.random() * tiles);
  };

  const reset = () => {
    snakeHead.x = Math.floor(tiles / 2);
    snakeHead.y = snakeHead.x;
    snakeHead.vx = 0;
    snakeHead.vy = -1;
    snakeTail = [{ ...snakeHead }];
    randomApple();
  };

  reset();

  const onKey = ({ code }) => {
    switch (code) {
      case "ArrowUp":
        snakeHead.vx = 0;
        snakeHead.vy = -1;
        break;
      case "ArrowDown":
        snakeHead.vx = 0;
        snakeHead.vy = 1;
        break;
      case "ArrowLeft":
        snakeHead.vx = -1;
        snakeHead.vy = 0;
        break;
      case "ArrowRight":
        snakeHead.vx = 1;
        snakeHead.vy = 0;
        break;
      default:
        break;
    }
  };

  let interval;

  const start = (ctx, finishScore, onFinish) => {
    document.addEventListener("keydown", onKey);
    interval = setInterval(() => {
      snakeHead.x += snakeHead.vx;
      snakeHead.y += snakeHead.vy;

      if (
        snakeHead.x < 0 ||
        snakeHead.x >= tiles ||
        snakeHead.y < 0 ||
        snakeHead.y >= tiles ||
        snakeTail.find(({ x, y }) => x === snakeHead.x && y === snakeHead.y)
      ) {
        reset();
      }

      snakeTail.push({ ...snakeHead });

      if (apple.x === snakeHead.x && apple.y === snakeHead.y) {
        randomApple();
      } else {
        snakeTail.shift();
      }

      const finished = snakeTail.length >= finishScore;

      ctx.fillStyle = "black";
      ctx.fillRect(0, 0, rawSize, rawSize);

      snakeTail.forEach(({ x, y }) => {
        drawTile(ctx, x, y, "green");
      });

      if (!finished) {
        drawTile(ctx, apple.x, apple.y, "red");
      }
      ctx.font = "24px serif";
      ctx.fillStyle = "#fff";
      ctx.textAlign = "left";
      ctx.textBaseline = "top";
      ctx.fillText(`${snakeTail.length}/${finishScore}`, tileSize, tileSize);

      if (finished) {
        clearInterval(interval);
        interval = null;

        ctx.font = "48px serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText("Done!", rawSize / 2, rawSize / 2);

        setTimeout(onFinish, 1000);
      }
    }, 50);
  };

  const stop = () => {
    document.removeEventListener("keydown", onKey);
    if (interval) {
      clearInterval(interval);
    }
  };

  return { start, stop, onKey };
};

const GunGame = ({ points, onFinish }) => {
  const ref = useRef();
  useEffect(() => {
    const { start, stop } = snakeGame();
    start(ref.current?.getContext("2d"), 10, onFinish);
    return () => {
      stop();
    };
  }, [onFinish]);

  return (
    <div className={styles.gungame}>
      <div className={styles.gungame_panel}>
        <div className={styles.gungame_label}>
          <div>Not good enough! That guess only got {points} points!</div>
          <div>Finish this snake game to try again!</div>
        </div>
        <canvas
          className={styles.gungame_canvas}
          ref={ref}
          width={rawSize}
          height={rawSize}
        />
      </div>
    </div>
  );
};

export default GunGame;
