#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <stdlib.h> // Include the standard library for random number generation

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define RIGHT 0
#define UP    1
#define LEFT  2
#define DOWN  3

#define BUTTON_DOWN  2
#define BUTTON_RIGHT 18
#define BUTTON_LEFT  19
#define BUTTON_UP    5

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

int score = 0;
int level = 1;
int gamespeed = 100;
int i;

const uint8_t ele[] PROGMEM = {
  0xf0, //B11110000
  0xb0, //B10110000
  0xd0, //B11010000
  0xf0, //B11110000
};

void element(int x, int y) {
  display.drawBitmap(x, y, ele, 4, 4, 1);
}

struct FOOD {
  int x;
  int y;
  int yes;
};

FOOD food = {5, 50, 1};

struct SNAKE {
  int x[200];
  int y[200];
  int node;
  int dir;
  int lefe;
};

SNAKE snake = {{9, 5}, {30, 30}, 2, RIGHT, 0};

void UI() {
  display.drawRect(0, 1, 128, 64, WHITE);
  display.drawRect(0, 0, 128, 64, WHITE);
}

void printScore(int x, int y, int s) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
}

void key() {
  if (digitalRead(BUTTON_DOWN) == LOW) {
    snake.dir = DOWN;
  }
  if (digitalRead(BUTTON_RIGHT) == LOW) {
    snake.dir = RIGHT;
  }
  if (digitalRead(BUTTON_LEFT) == LOW) {
    snake.dir = LEFT;
  }
  if (digitalRead(BUTTON_UP) == LOW) {
    snake.dir = UP;
  }
}

void snakeGame() {
  switch (snake.dir) {
    case RIGHT:
      snake.x[0] += 4;
      if (snake.x[0] >= 101) {
        snake.x[0] = 1;
      }
      break;
    case UP:
      snake.y[0] -= 4;
      if (snake.y[0] <= 1) {
        snake.y[0] = 58;
      }
      break;
    case LEFT:
      snake.x[0] -= 4;
      if (snake.x[0] <= 0) {
        snake.x[0] = 97;
      }
      break;
    case DOWN:
      snake.y[0] += 4;
      if (snake.y[0] >= 62) {
        snake.y[0] = 2;
      }
      break;
  }
  if ((snake.x[0] == food.x) && (snake.y[0] == food.y)) {
    snake.x[0] = food.x;
    snake.y[0] = food.y;
    snake.node++;
    food.yes = 1;
    score += 2;
    level = score / 10 + 1;
    generateFood(); // Generate new food
  }
  if ((snake.x[0] == food.y) && (snake.y[0] == food.x)) {
    snake.x[0] = food.y;
    snake.y[0] = food.x;
    snake.node++;
    food.yes = 1;
    score += 2;
    level = score / 10 + 1;
    generateFood(); // Generate new food
  }
  for (i = snake.node - 1; i > 0; i--) {
    snake.x[i] = snake.x[i - 1];
    snake.y[i] = snake.y[i - 1];
  }
}

void generateFood() {
  // Generate random x and y coordinates for food within the screen bounds
  food.x = random(1, 128);
  food.y = random(1, 64);
}

void setup() {
  pinMode(BUTTON_DOWN, INPUT_PULLUP);
  pinMode(BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(BUTTON_LEFT, INPUT_PULLUP);
  pinMode(BUTTON_UP, INPUT_PULLUP);

  // Initialize random seed
  randomSeed(analogRead(0));

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {
  display.clearDisplay();
  UI();
  for (i = 0; i < snake.node; i++) {
    element(snake.x[i], snake.y[i]);
  }
  element(food.x, food.y);

  display.display();

  key();
  snakeGame();
  delay(gamespeed);
}