#include <TFT_eSPI.h>
#include "dino.h"

// --- Configurações do Display ---
TFT_eSPI tft = TFT_eSPI();

// --- Definições do Jogo ---
#define SCREEN_WIDTH  320
#define SCREEN_HEIGHT 240
#define GROUND_Y      SCREEN_HEIGHT - 40
#define JUMP_HEIGHT   80
#define DINO_X_POS    20
#define DINO_WIDTH    40
#define DINO_HEIGHT   44
#define CACTUS_WIDTH  24
#define CACTUS_HEIGHT 48
#define JUMP_BTN      0 // Pino para o botão de pulo (use o pino BOOT do ESP32)

// --- Variáveis do Jogo ---
int dino_y = GROUND_Y - DINO_HEIGHT;
int dino_y_velocity = 0;
bool is_jumping = false;
unsigned long score = 0;
int game_speed = 6;
bool game_over = false;

struct Obstacle {
  int x;
  bool active;
};

Obstacle cactus;

void setup() {
  Serial.begin(115200);
  pinMode(JUMP_BTN, INPUT_PULLUP);

  tft.init();
  tft.setRotation(1); // Ajuste a rotação conforme necessário
  tft.fillScreen(TFT_WHITE);

  startGame();
}

void loop() {
  if (!game_over) {
    handleInput();
    updateGame();
    draw();
    delay(30); // Controla a velocidade geral do jogo
  } else {
    // Se o jogo acabou, espera o botão ser pressionado para reiniciar
    if (digitalRead(JUMP_BTN) == LOW) {
      startGame();
    }
  }
}

void startGame() {
  tft.fillScreen(TFT_WHITE);
  drawGround();
  
  dino_y = GROUND_Y - DINO_HEIGHT;
  dino_y_velocity = 0;
  is_jumping = false;
  score = 0;
  game_speed = 6;
  game_over = false;

  cactus.x = SCREEN_WIDTH;
  cactus.active = true;
  
  tft.setTextColor(TFT_BLACK);
  tft.setTextSize(2);
}

void handleInput() {
  // Pula se o botão for pressionado e o dinossauro não estiver pulando
  if (digitalRead(JUMP_BTN) == LOW && !is_jumping) {
    is_jumping = true;
    dino_y_velocity = -18; // Força inicial do pulo
  }
}

void updateGame() {
  // Atualiza a posição do dinossauro (pulo)
  if (is_jumping) {
    dino_y += dino_y_velocity;
    dino_y_velocity += 1; // Gravidade

    if (dino_y >= GROUND_Y - DINO_HEIGHT) {
      dino_y = GROUND_Y - DINO_HEIGHT;
      is_jumping = false;
      dino_y_velocity = 0;
    }
  }

  // Move o cacto
  if (cactus.active) {
    cactus.x -= game_speed;
    if (cactus.x < -CACTUS_WIDTH) {
      cactus.x = SCREEN_WIDTH + random(0, 100);
    }
  }
  
  // Aumenta a velocidade com o tempo
  if(score > 0 && score % 100 == 0) {
    game_speed++;
  }

  // Detecção de colisão
  if (cactus.active &&
      DINO_X_POS + DINO_WIDTH > cactus.x &&
      DINO_X_POS < cactus.x + CACTUS_WIDTH &&
      dino_y + DINO_HEIGHT > GROUND_Y - CACTUS_HEIGHT) {
    gameOver();
  }

  score++;
}

void draw() {
  // Limpa a área do jogo
  tft.fillRect(0, 0, SCREEN_WIDTH, GROUND_Y - 1, TFT_WHITE);
  
  // Desenha o dinossauro
  static bool dino_frame = true;
  if(is_jumping){
      tft.drawXBitmap(DINO_X_POS, dino_y, dino_run1_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
  } else {
    if (dino_frame) {
      tft.drawXBitmap(DINO_X_POS, dino_y, dino_run1_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
    } else {
      tft.drawXBitmap(DINO_X_POS, dino_y, dino_run2_bits, DINO_WIDTH, DINO_HEIGHT, TFT_BLACK);
    }
  }
  dino_frame = !dino_frame; // Alterna o frame da animação de corrida

  // Desenha o cacto
  if (cactus.active) {
    tft.drawXBitmap(cactus.x, GROUND_Y - CACTUS_HEIGHT, cactus_bits, CACTUS_WIDTH, CACTUS_HEIGHT, TFT_BLACK);
  }

  // Desenha o chão
  drawGround();
  
  // Desenha a pontuação
  tft.setCursor(10, 10);
  tft.print("Score: ");
  tft.print(score);
}

void drawGround() {
  tft.drawFastHLine(0, GROUND_Y, SCREEN_WIDTH, TFT_BLACK);
}

void gameOver() {
  game_over = true;
  tft.setCursor(SCREEN_WIDTH / 2 - 80, SCREEN_HEIGHT / 2 - 20);
  tft.setTextColor(TFT_BLACK);
  tft.setTextSize(3);
  tft.print("GAME OVER");
  
  tft.setCursor(SCREEN_WIDTH / 2 - 120, SCREEN_HEIGHT / 2 + 20);
  tft.setTextSize(2);
  tft.print("Pressione para reiniciar");
}