#include <TVout.h>
#include <TVoutfonts/fontALL.h>

#include "logo.h"

#define PLAYER1_INPUT A0
#define PLAYER2_INPUT A1

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 96

#define TOP_LIMIT 9
#define INF_LIMIT 86

TVout TV;

// Configuraçoes
int speedGame = 25;
int speedBallX = 1;
int speedBallY = -1;

boolean startGame = false;
boolean ownerBall = true;

// Coordenadas dos players
int posPlayer1X = 5;
int posPlayer1Y;
int posPlayer2X = 114;
int posPlayer2Y;
int dirPlayer1;
int dirPlayer2;

// Coordenada da bola
int posBallX = 7;
int posBallY;

// Pontuacao dos players
int pointsPlayer1 = 0;
int pointsPlayer2 = 0;

void setup() {
  TV.begin(_PAL, SCREEN_WIDTH, SCREEN_HEIGHT);

  posPlayer1Y = map(analogRead(PLAYER1_INPUT), 0, 1023, 16, 79);
  posPlayer2Y = map(analogRead(PLAYER2_INPUT), 0, 1023, 16, 79);

  dirPlayer1 = posPlayer1Y;
  dirPlayer2 = posPlayer2Y;

  posBallY = posPlayer1Y;

  TV.clear_screen();

  // Desenha borda
  TV.draw_rect(0, 0, TV.hres() - 1, TV.vres() - 1, 1);
  TV.draw_rect(1, 1, TV.hres() - 3, TV.vres() - 3, 1);

  // Desenha logo
  TV.bitmap((TV.hres() - pong_logo[0]) / 2, (TV.vres() - pong_logo[1]) / 2, pong_logo);
  delay(1000);
}

void loop() {
  drawScene();
  checkMotionPlayers();
  movesBall();

  delay(speedGame);

  if (pointsPlayer1 == 5) {
    gameOver(1);
  } else if (pointsPlayer2 == 5) {
    gameOver(2);
  }
}

void drawScene() {
  // Desenha a posicao dos player
  TV.clear_screen();
  TV.select_font(font6x8);
  TV.print(44, 0, pointsPlayer1);
  TV.print(70, 0, pointsPlayer2);
  TV.select_font(font4x6);

  // Desenha quadra retangular
  TV.draw_rect(0, 8, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 17, WHITE);

  // Desenha coluna central da quadra
  for (int i = 9; i <= 85; i = i + 5) {
    TV.draw_column((SCREEN_WIDTH / 2) - 1, i, i + 2, WHITE);
  }

  // Desenha player 1
  TV.draw_column(posPlayer1X, (posPlayer1Y - 7), (posPlayer1Y + 7), WHITE);

  // Desenha player 2
  TV.draw_column(posPlayer2X, (posPlayer2Y - 7), (posPlayer2Y + 7), WHITE);

  // Desenha bola
  TV.set_pixel(posBallX, posBallY, WHITE);
}

void checkMotionPlayers() {
  posPlayer1Y = map(analogRead(PLAYER1_INPUT), 0, 1023, 16, 79);

  if (dirPlayer1 < posPlayer1Y) {
    if (!startGame && ownerBall) {
      speedBallY = 1;
      startGame = true;
    }
  } else if (dirPlayer1 > posPlayer1Y) {
    if (!startGame && ownerBall) {
      speedBallY = -1;
      startGame = true;
    }
  }

  posPlayer2Y = map(analogRead(PLAYER2_INPUT), 0, 1023, 16, 79);

  if (dirPlayer2 < posPlayer2Y) {
    if (!startGame && !ownerBall) {
      speedBallY = 1;
      startGame = true;
    }
  } else if (dirPlayer2 > posPlayer2Y) {
    if (!startGame && !ownerBall) {
      speedBallY = -1;
      startGame = true;
    }
  }

  dirPlayer1 = posPlayer1Y;
  dirPlayer2 = posPlayer2Y;
}

void movesBall() {
  int ballX = posBallX;
  int ballY = posBallY;

  if (startGame) {
    ballX = posBallX + speedBallX;
    ballY = posBallY + speedBallY;
  }

  // Verifica colisoes superior e inferior da bola com a quadra
  if (ballY == TOP_LIMIT) {
    speedBallY = 1;
    soundGame(440, 20); // Sonoro quando a bola bate na parte superior
  }
  else if (ballY == INF_LIMIT) {
    speedBallY = -1;
    soundGame(440, 20); // Sonoro quando a bola bate na parte inferior
  }

  // Verifica colisoes da bola com os players
  // Player 1
  if (ballX == 7) {
    if (posBallY < posPlayer1Y + 8 && posBallY > posPlayer1Y - 8) {
      speedBallX = 1;
      if (startGame) {
        soundGame(220, 20); // Sonoro quando player 1 bate na bola
      }
    }
  } else if (ballX == 0) {
    startGame = false;
    ownerBall = false;
    ballX = 112;
    ballY = posPlayer2Y;
    pointsPlayer2++;
    soundGame(100, 300); // Sonoro quando player 2 faz ponto
  }

  // Player 2
  if (ballX == 112) {
    if (posBallY < posPlayer2Y + 8 && posBallY > posPlayer2Y - 8) {
      speedBallX = -1;
      if (startGame) {
        soundGame(220, 20); // Sonoro quando player 2 bate na bola
      }
    }
  } else if (ballX == SCREEN_WIDTH) {
    startGame = false;
    ownerBall = true;
    ballX = 7;
    ballY = posPlayer1Y;
    pointsPlayer1++;
    soundGame(100, 300); // Sonoro quando player 1 faz ponto
  }

  posBallX = ballX;
  posBallY = ballY;
}

void soundGame(int frequency, int duration) {
  TV.tone(frequency, duration);
}

void gameOver(byte winner) {
  startGame = false;

  pointsPlayer1 = 0;
  pointsPlayer2 = 0;

  TV.clear_screen();
  TV.select_font(font8x8);

  soundGame(520, 500); // Sonoro quando player 1 ou player 2 vence o jogo

  if (winner == 1) {
    ownerBall = true;
    TV.println(27, 40, "Winner");
    TV.println(27, 50, "PLAYER 1");
  } else if (winner == 2) {
    ownerBall = false;
    TV.println(27, 40, "Winner");
    TV.println(27, 50, "PLAYER 2");
  }

  delay(5000);
}