// Objecten
let imgBackground;
let sndClick;
let sndCheer;
let sndBoo;
let mscBackground;

let buttonStart;
let player1NameInput;
let player2NameInput;
let player3NameInput;

let buttonSelect3X3;
let buttonSelect4X4;
let buttonSelect5X5;
let buttonSelectVSAI;

let buttonRestart;
let buttonQuit;

let buttonPlayer1Red;
let buttonPlayer1Pink;
let buttonPlayer2Blue;
let buttonPlayer2Cyan;
let buttonPlayer3Yellow;
let buttonPlayer3Orange;


// Enums
const gameStates = {
  Playing: "Playing",
  MainMenu: "MainMenu",
  Settings: "Settings",
  RedWon: "RedWon",
  BlueWon: "BlueWon",
  YellowWon: "YellowWon",
  Tie: "Tie",
}

const gameModes = {
  ThreeXThree: "ThreeXThree",
  FourXFour: "FourXFour",
  FiveXFive: "FiveXFive",
  vsAI: "vsAI",
}

const winTypes = {
  row: "row",
  column: "column",
  diagonal1: "diagonal1",
  diagonal2: "diagonal2",
}

// Variabelen

let grid = [
  [0, 0, 0],
  [0, 0, 0],
  [0, 0, 0]
]

let gameState = gameStates.MainMenu;
let chosenGamemode = gameModes.ThreeXThree;

let winType;
let winColumn = 0;
let winRow = 0;

let column = 0;
let rows = 0;

let circlePlayer1X = -1000;
let circlePlayer2X = 1500;
let circlePlayer3Y = 1500;

let circlePlayer1TargetX = -1000;
let circlePlayer2TargetX = 1500;
let circlePlayer3TargetY = 1500;

let backgroundX = -1000;

let player1Name = "Jolanda";
let player2Name = "Gert";
let player3Name = "Hendrik";

let textRotation = 0;
let sizeOfText = 100; // Rare naam want textSize is al een functie

let textGrowTarget = 50;
let textRotationTarget = 50;

let playerTurn = 1;
let totalPlayers = 2;

let turn = 0;
let totalTurns = 9;

let plr1Color;
let plr2Color;
let plr3Color;

// Consts
const white = "#ffffffff"
const blue = "#3c45cdff";
const cyan = "#13c1e8ff";
const red = "#e81313ff";
const pink = "#e813cfff";
const yellow = "rgba(229, 255, 0, 255)";
const orange = "#f49106ff";
const grey = "#474a4cff";
const greySelected = "#1b1c1dff";

const canvasXsize = 1000;
const canvasYsize = 1000;

const AIPlayerNumber = 2;

function preload() {
  imgBackground = loadImage("/../assets_week_3/images/background.png");
  sndClick = loadSound("/../assets_week_3/sounds/ButtonOnClick.ogg");
  sndCheer = loadSound("/../assets_week_3/sounds/cheer.ogg");
  sndBoo = loadSound("/../assets_week_3/sounds/Boo.ogg")
  mscBackground = loadSound("/../assets_week_3/sounds/Music.ogg");
}

function setup() { // In godot is dit de ready function
  createCanvas(canvasXsize, canvasYsize);
  angleMode(DEGREES); // Zorg dat alles in graden draait

  // Volume instellingen
  mscBackground.setVolume(0.5)
  sndClick.rate(0.5);

  // Default kleuren
  plr1Color = red;
  plr2Color = blue;
  plr3Color = yellow;

  // Muziek
  mscBackground.loop();

  // Maak objecten
  buttonStart = createButton("Start");
  buttonSelect3X3 = createButton("3X3");
  buttonSelect4X4 = createButton("4X4");
  buttonSelect5X5 = createButton("5x5");
  buttonSelectVSAI = createButton("vs AI");
  buttonRestart = createButton("Restart");
  buttonQuit = createButton("Quit");
  buttonPlayer1Red = createButton("Rood");
  buttonPlayer1Pink = createButton("Roze");
  buttonPlayer2Blue = createButton("Blauw");
  buttonPlayer2Cyan = createButton("Cyaan");
  buttonPlayer3Orange = createButton("Oranje");
  buttonPlayer3Yellow = createButton("Geel");
  player1NameInput = createInput(player1Name).attribute('maxlength', 7); // Maak max lengte zodat het niet te lang word
  player2NameInput = createInput(player2Name).attribute('maxlength', 7);
  player3NameInput = createInput(player3Name).attribute('maxlength', 7);

  // Button start setup
  buttonStart.style("background", "#e81313ff");
  buttonStart.style("border-color", "#ab1010ff");
  buttonStart.style("border-width", "10px");
  buttonStart.style("border-height", "10px");
  buttonStart.style("border-radius", "10px");
  buttonStart.style("font-size", "96px");
  buttonStart.size(250, 150);

  buttonStart.mousePressed(on_start_clicked);

  // Zet functies van alle overige knopjes
  buttonSelect3X3.mousePressed(_on_3x3_clicked);
  buttonSelect4X4.mousePressed(_on_4x4_clicked);
  buttonSelect5X5.mousePressed(_on_5x5_clicked);
  buttonSelectVSAI.mousePressed(_on_vsAI_clicked);
  buttonRestart.mousePressed(_on_restart_clicked);
  buttonQuit.mousePressed(_on_quit_clicked);
  buttonPlayer1Pink.mousePressed(_on_buttonPlayer1Pink_clicked);
  buttonPlayer1Red.mousePressed(_on_buttonPlayer1Red_clicked);
  buttonPlayer2Blue.mousePressed(_on_buttonPlayer2Blue_clicked);
  buttonPlayer2Cyan.mousePressed(_on_buttonPlayer2Cyan_clicked);
  buttonPlayer3Orange.mousePressed(_on_buttonPlayer3Orange_clicked);
  buttonPlayer3Yellow.mousePressed(_on_buttonPlayer3Yellow_clicked);

  // quit/Restart knop styling
  buttonRestart.style("background", "#e81313ff");
  buttonRestart.style("border-color", "#ab1010ff");
  buttonRestart.style("border-width", "10px");
  buttonRestart.style("border-height", "10px");
  buttonRestart.style("border-radius", "10px");
  buttonRestart.style("font-size", "32px");
  buttonRestart.size(150, 150);
  buttonRestart.position(700, 850);

  buttonQuit.style("background", "#e81313ff");
  buttonQuit.style("border-color", "#ab1010ff");
  buttonQuit.style("border-width", "10px");
  buttonQuit.style("border-height", "10px");
  buttonQuit.style("border-radius", "10px");
  buttonQuit.style("font-size", "32px");
  buttonQuit.size(150, 150);
  buttonQuit.position(200, 850);

  // Overige posities
  buttonPlayer1Red.position(350, 500);
  buttonPlayer1Pink.position(400, 500);

  buttonPlayer2Blue.position(350, 575);
  buttonPlayer2Cyan.position(400, 575);

  buttonPlayer3Yellow.position(350, 650);
  buttonPlayer3Orange.position(400, 650);

  buttonSelect3X3.position(350, 725);
  buttonSelect4X4.position(400, 725);
  buttonSelect5X5.position(450, 725);
  buttonSelectVSAI.position(500, 725)

  // Naam inputs
  player1NameInput.input(update_names);
  player2NameInput.input(update_names);
  player3NameInput.input(update_names);

  player1NameInput.position(350, 200);
  player2NameInput.position(350, 300);
  player3NameInput.position(350, 400);

  player1NameInput.style("font-size", "32px");
  player1NameInput.style("background", "#d0c8c8ff")

  player2NameInput.style("font-size", "32px");
  player2NameInput.style("background", "#d0c8c8ff")

  player3NameInput.style("font-size", "32px");
  player3NameInput.style("background", "#d0c8c8ff")
}

function draw() { // In godot is dit de process function
  background(220);

  // Achtergrondbeweging

  backgroundX++;
  if (backgroundX >= 0) {
    backgroundX = -1000;
  }

  image(imgBackground, backgroundX, 0);

  // Berekening

  if (sizeOfText >= 99 || textRotation >= 49) { // Reset samen
    textGrowTarget = 49;
    textRotationTarget = -51;
  }
  else if (sizeOfText <= 51 || textRotation <= -50) {
    textGrowTarget = 101;
    textRotationTarget = 51;
  }

  sizeOfText = lerp(sizeOfText, textGrowTarget, 0.05);
  textRotation = lerp(textRotation, textRotationTarget, 0.05);

  // Player beurt dingen positie

  circlePlayer1X = lerp(circlePlayer1X, circlePlayer1TargetX, 0.05);
  circlePlayer2X = lerp(circlePlayer2X, circlePlayer2TargetX, 0.05);
  circlePlayer3Y = lerp(circlePlayer3Y, circlePlayer3TargetY, 0.05);


  // Tekst instellingen

  textAlign(CENTER, CENTER);
  textSize(sizeOfText);
  noStroke();

  // Check game status

  switch (gameState) {
    case gameStates.MainMenu:
      _main_menu();
      break;
    case gameStates.Settings:
      _settings();
      break;
    case gameStates.Playing:
      _in_game();
      break;
    case gameStates.Tie:
    case gameStates.YellowWon:
    case gameStates.BlueWon:
    case gameStates.RedWon: // Spel is voorbij
      buttonRestart.show();
      buttonQuit.show();

      _draw_board();
      _show_winner_text();
      
      if (gameState != gameStates.Tie) {
      _show_win_lines();
      }

      break;
  }

  resetMatrix();
  textSize(20);
  column = floor((mouseX - 250) / (500 / grid.length));
  rows = floor((mouseY - 250) / (500 / grid.length));
}


function _main_menu() {
  // Knopjes

  buttonStart.position(canvasXsize / 3, canvasYsize / 1.5); 

  buttonStart.show();

  player1NameInput.hide();
  player2NameInput.hide();
  player3NameInput.hide();

  buttonSelect3X3.hide();
  buttonSelect4X4.hide();
  buttonSelect5X5.hide();
  buttonSelectVSAI.hide();

  buttonPlayer1Pink.hide();
  buttonPlayer1Red.hide();
  buttonPlayer2Blue.hide();
  buttonPlayer2Cyan.hide();
  buttonPlayer3Orange.hide();
  buttonPlayer3Yellow.hide();

  buttonQuit.hide();
  buttonRestart.hide();

  // Text
  stroke(0);
  strokeWeight(round(sizeOfText / 25));
  fill(white);
  translate(canvasXsize / 2, canvasYsize / 2);
  rotate(textRotation / 2);
  text("Boter, kaas,\nen eieren!", 0, -250);

}

function _settings() {
  // Knopjes

  buttonStart.position(canvasXsize / 3, canvasYsize / 1.2);

  buttonStart.show();

  player1NameInput.show();
  player2NameInput.show();
  player3NameInput.show();

  buttonSelect3X3.show();
  buttonSelect4X4.show();
  buttonSelect5X5.show();
  buttonSelectVSAI.show();

  buttonPlayer1Pink.show();
  buttonPlayer1Red.show();
  buttonPlayer2Blue.show();
  buttonPlayer2Cyan.show();
  buttonPlayer3Orange.show();
  buttonPlayer3Yellow.show();

  buttonQuit.hide();
  buttonRestart.hide();

  // Tekst
  textAlign(LEFT, LEFT);
  textSize(32);
  text("Player 1 naam:", 350, 175);
  text("Player 2 naam:", 350, 275);
  text("Player 3 naam: (5x5 exclusief)", 350, 375);
  text("Player 1 kleur selectie", 350, 475);
  text("Player 2 kleur selectie", 350, 550);
  text("Player 3 kleur selectie", 350, 625);
  text("Gamemode selectie", 350, 700);
  
}

function _in_game() {
  // knopjes
  player1NameInput.hide();
  player2NameInput.hide();
  player3NameInput.hide();

  buttonStart.hide();

  buttonSelect3X3.hide();
  buttonSelect4X4.hide();
  buttonSelect5X5.hide();
  buttonSelectVSAI.hide();

  buttonPlayer1Pink.hide();
  buttonPlayer1Red.hide();
  buttonPlayer2Blue.hide();
  buttonPlayer2Cyan.hide();
  buttonPlayer3Orange.hide();
  buttonPlayer3Yellow.hide();

   buttonQuit.hide();
   buttonRestart.hide();

  
  // functies
  _draw_board();
  _display_turn_text();
  _draw_player_turn_circle();

  if (chosenGamemode === gameModes.vsAI && playerTurn === AIPlayerNumber) {
    _choose_random_placement(); // Als AIs beurt, laat hem een plaats zoeken
  }
}

function _display_turn_text() { // Laat correcte tekst zien
  round(sizeOfText / 25);
  stroke(0);
  fill(white);
  switch (playerTurn) {
    case 1:
      fill(plr1Color);
      text(player1Name + "'s beurt!", 500, 100);
      break;
    case 2:
      fill(plr2Color);
      text(player2Name + "'s beurt!", 500, 100);
      break;
    case 3:
      fill(plr3Color);
      text(player3Name + "'s beurt!", 500, 100);
      break;
  }
}

function _draw_board() {

  fill(100);
  strokeWeight(10);
  stroke(100);
  rect(250, 250, 500, 500, 50, 50);

  if (rows < grid.length && rows >= 0 && column < grid[rows].length
    && column >= 0 && grid[rows][column] === 0) {
    grid[rows][column] = -1; // hover kleur
  }

  for (let l = 0; l < grid.length; l++) { // lengte van array
    for (let w = 0; w < grid[l].length; w++) {

      let value = grid[l][w]; // Krijg waarde van array

      if ((l != rows || w != column) && grid[l][w] === -1) { // Reset kleur
        grid[l][w] = 0;
      }

      switch (value) { // Maak juiste kleur
        case -1:
          fill(greySelected);
          break;
        case 0:
          fill(grey);
          break;
        case 1:
          fill(plr1Color);
          break;
        case 2:
          fill(plr2Color)
          break;
        case 3:
          fill(plr3Color);
          break;
      }

      rect(250 + w * (500 / grid.length), 250 + l * (500 / grid.length), 500 / grid.length, 500 / grid.length, 20, 20); // maak kubussen
    }
  }
}

function _check_for_win() {

  turn += 1; // voegt beurt toe

  let size = grid.length;

  for (let playerChecked = 1; playerChecked < totalPlayers + 1; playerChecked++) {

    for (let l = 0; l < size; l++) { // rows check (boven naar beneden)
      let win = true; // Maak win variabel aan, reset voor elke keer in size

      for (let checked = 0; checked < size; checked++) {

        if (grid[l][checked] != playerChecked) { // Check rijen
          win = false // Als niet van speler, zet win naar false
        }
      }
      if (win === true) {
        sndCheer.play();
        _set_winner(playerChecked);
        winType = winTypes.row;
        winRow = l;
      }
    }
    for (let l = 0; l < size; l++) { // column check (links naar rechts)
      let win = true;

      for (let checked = 0; checked < size; checked++) {

        if (grid[checked][l] != playerChecked) { // draai checked en grid om zodat het columnen checked
          win = false 
        }
      }
      if (win === true) {
        sndCheer.play();
        winColumn = l;
        _set_winner(playerChecked);
        winType = winTypes.column;
      
      }
    }
      // diagonaal check in deze vorm: /
      let winDiagonal = true; // Nieuwe variabel dat niet reset

      for (let checked = 0; checked < size; checked++) {

        if (grid[checked][size - 1 - checked] != playerChecked) {  // size - 1 - checked start bij eind punt en doet voor elke check er 1 af.
          winDiagonal = false;
        }
      }
      if (winDiagonal === true) {
        sndCheer.play();
        winType = winTypes.diagonal1;
        _set_winner(playerChecked);
      }
      // diagonaal check in deze vorm: \
      let winDiagonal2 = true; // reset niet want maar 1 check
      for (let checked = 0; checked < size; checked++) {

        if (grid[checked][checked] != playerChecked) {  // Checked checked zodat [0,0], [1,1], etc
          winDiagonal2 = false;
        }
      }
      if (winDiagonal2 === true) {
        sndCheer.play();
        _set_winner(playerChecked);
        winType = winTypes.diagonal2;
      }
    }

    if (turn === totalTurns && gameState === gameStates.Playing) {
      sndBoo.play();
      gameState = gameStates.Tie;
    }
  }

function _set_winner(winner) {
  switch(winner) {
    case 1:
      gameState = gameStates.RedWon;
      break;
    case 2:
      gameState = gameStates.BlueWon;
      break;
    case 3:
      gameState = gameStates.YellowWon;
      break;
  }
}

function _show_win_lines() {

  // Lijn instellingen
  strokeWeight(10);
  stroke(white);

  switch(winType) {
    case winTypes.row:
      line(250, 250 + (winRow + 0.5) * (500 / grid.length), 750, 250 + (winRow + 0.5) * (500 / grid.length));
      break;
    case winTypes.column:
      line(250 + (winColumn + 0.5) * (500 / grid.length), 250, 250 + (winColumn + 0.5) * (500 / grid.length), 750);
      break;
    case winTypes.diagonal1:
      line(750, 250, 250, 750);
      break;
    case winTypes.diagonal2:
      line(250, 250, 750, 750);
      break;
  }
}

function mousePressed() {
  if (gameState === gameStates.Playing && mouseButton == LEFT) {
    if (rows < grid.length && rows >= 0 && column < grid[rows].length
      && column >= 0 && (grid[rows][column] === 0 || grid[rows][column] === - 1)) { // Check of geselecteerd en geen error veroorzaken


        if (chosenGamemode != gameModes.vsAI || playerTurn != AIPlayerNumber) { // Als vsAI, doe alleen als eigen beurt
        
        sndClick.play();

        grid[rows][column] = playerTurn; // Zorg ervoor dat het de juiste kleur wordt

        if (playerTurn >= totalPlayers) { // Maak beurt correct
          playerTurn = 1;
        }
        else {
          playerTurn++;
        }

        _set_correct_player_positions();


        _check_for_win();
      }

    }
  }
}

function _show_winner_text() {
  fill(white);
  strokeWeight(5);
  stroke(0);
  switch (gameState) {
    case gameStates.RedWon:
      text(player1Name + " wint!", 500, 200);
      break;
    case gameStates.BlueWon:
      text(player2Name + " wint!", 500, 200);
      break;
    case gameStates.YellowWon:
      text(player3Name + " wint!", 500, 200);
      break;
    case gameStates.Tie:
      text("Gelijk spel!", 500, 200);
      break;
  }
}

function _draw_player_turn_circle() {

  stroke(0);
  strokeWeight(3);

  // Speler 1
  fill(plr1Color);
  circle(circlePlayer1X, 500, 250);

  // Speler 2
  fill(plr2Color);
  circle(circlePlayer2X, 500, 250);

  // Speler 3
  fill(plr3Color);
  circle(500, circlePlayer3Y, 250);
}

function _set_correct_player_positions() {
  switch (playerTurn) { // Zet juiste posities 
    case 1:
      circlePlayer1TargetX = 0;
      circlePlayer2TargetX = 1500;
      circlePlayer3TargetY = 1500;
      break;
    case 2:
      circlePlayer1TargetX = -1000;
      circlePlayer2TargetX = 1000;
      circlePlayer3TargetY = 1500;
      break;
    case 3:
      circlePlayer1TargetX = -1000;
      circlePlayer2TargetX = 1500;
      circlePlayer3TargetY = 1000;
      break;
  }
}

function _on_restart_clicked() { // Restart knop
  _reset_game(gameStates.Playing);
}

function _on_quit_clicked() {
  _reset_game(gameStates.MainMenu);
}

function _reset_game(newState) {
  turn = 0;

  switch (chosenGamemode) { // Reset grid voor juiste gamemode
    case gameModes.ThreeXThree:
      _on_3x3_clicked();
      break;
    case gameModes.FourXFour:
      _on_4x4_clicked();
      break;
    case gameModes.FiveXFive:
      _on_5x5_clicked();
      break;
    case gameModes.vsAI:
      _on_vsAI_clicked();
      break;
  }

  gameState = newState; // reset naar juiste state
}

function on_start_clicked() {

  playerTurn = 1;

  _set_correct_player_positions();
  sndClick.play();
  switch (gameState) {
    case gameStates.MainMenu:
      gameState = gameStates.Settings;
      break;
    case gameStates.Settings:
      gameState = gameStates.Playing;
      turn = 0;
      break;
  }
}

// Kleur Knopjes

function _on_buttonPlayer1Red_clicked(){
  plr1Color = red;
}

function _on_buttonPlayer1Pink_clicked(){
  plr1Color = pink;
}

function _on_buttonPlayer2Blue_clicked(){
  plr2Color = blue;
}

function _on_buttonPlayer2Cyan_clicked(){
  plr2Color = cyan;
}

function _on_buttonPlayer3Yellow_clicked(){
  plr3Color = yellow;
}

function _on_buttonPlayer3Orange_clicked(){
  plr3Color = orange;
}

function update_names() {
  sndClick.play();
  player1Name = player1NameInput.value();
  player2Name = player2NameInput.value();
  player3Name = player3NameInput.value();
}

// Gamemodes

function _on_3x3_clicked() {
  totalTurns = 9
  grid = [[0,0,0], [0,0,0], [0,0,0]];
  totalPlayers = 2;
  chosenGamemode = gameModes.ThreeXThree;
}

function _on_4x4_clicked() {
  totalTurns = 16;
  grid = [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]];
  totalPlayers = 2;
  chosenGamemode = gameModes.FourXFour;
}

function _on_5x5_clicked() {
  totalTurns = 25;
  grid = [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0]];
  chosenGamemode = gameModes.FiveXFive;
  totalPlayers = 3;
}

function _on_vsAI_clicked() {
  player2Name = "AI";
  totalTurns = 9;
  grid = [[0,0,0], [0,0,0], [0,0,0]];
  totalPlayers = 2;
  chosenGamemode = gameModes.vsAI;
}

// AI

function _choose_random_placement() {
  let size = grid.length; // grid grootte
  let placementX = round(random(0, size - 1));
  let placementY = round(random(0, size - 1)); // Krijg random positie

  // Check of in midden kan plaatsen (de meeste spelers plaatsen hier dus realistische eerste zet).

  if (grid[floor(size / 2)][floor(size / 2)] === 0 || grid[floor(size / 2)][floor(size / 2)] === -1) {
    placementX = floor(size / 2)
    placementY = floor(size / 2)
  }

  if (grid[placementX][placementY] === 0 || grid[placementX][placementY] === -1) { // Check of er niet iets is
    grid[placementX][placementY] = AIPlayerNumber; // Zet naar AIs kleur
    playerTurn = 1; // Zet turn terug naar 1
    sndClick.play();
    _check_for_win();
    _set_correct_player_positions();
  }
  else {
    _choose_random_placement(); // Als positie al vol is, probeer opnieuw
  }
}
