#include <FastLED.h>
#include "Snake.h"

#define NUM_LEDS      135
#define LEDS_PER_ROW  15
#define DATA_PIN      6

#define BTN_LEFT      2
#define BTN_RIGHT     4
#define BTN_UP        5
#define BTN_DOWN      3

// Initialize the snake field with x=15, y=9, delay=10 ticks
Snake snakeGame(15, 9, 10);

CRGB leds[NUM_LEDS];

void setup() {
  pinMode(BTN_LEFT, INPUT_PULLUP);
  pinMode(BTN_RIGHT, INPUT_PULLUP);
  pinMode(BTN_UP, INPUT_PULLUP);
  pinMode(BTN_DOWN, INPUT_PULLUP);

  snakeGame.setBodyColor(255, 0, 255); // Optionally set the color of the snakeparts
  snakeGame.setFoodColor(0, 60, 125); // Optionally set the color of the food
  snakeGame.setHeadColor(225, 20, 60); // Optionally set the color of the snakeparts
  
  delay(2000);

  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
}

void inputEvent(int poll_time) {
  uint32_t timeout = millis() + poll_time;
  do {
    if (digitalRead(BTN_LEFT) == LOW) {
      snakeGame.goLeft(); // Snake will go left on the next move
    }

    if (digitalRead(BTN_RIGHT) == LOW) {
      snakeGame.goRight(); // Snake will go right on the next move
    }

    if (digitalRead(BTN_UP) == LOW) {
      snakeGame.goUp(); // Snake will go up on the next move
    }

    if (digitalRead(BTN_DOWN) == LOW) {
      snakeGame.goDown(); // Snake will go down on the next move
    }
  } while (millis() < timeout);
}

byte setPixel(byte x, byte y, byte r, byte g, byte b)
{
  byte ledID = NUM_LEDS - (y * LEDS_PER_ROW) - x - 1 ;
  leds[ledID].setRGB(r, g, b);
  return ledID;
}

void changeRGBtoGBR()
{
  for (int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++)
  {
    leds[whiteLed].setRGB(leds[whiteLed].g, leds[whiteLed].b, leds[whiteLed].r);
  }
}

void clearScreen()
{
  for (int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++)
  {
    leds[whiteLed].setRGB( 3, 3, 3);
  }
}

void loop()
{
  inputEvent(30);

  Snake::pixel* snakeLimbs = snakeGame.getSnakeLimbs(); // This needs to be updated every frame
  Snake::pixel* snakeFood = snakeGame.getFoodPositions();// This needs to be updated every frame

  clearScreen();

  setPixel(snakeFood[0].posX, 8 - snakeFood[0].posY, snakeFood[0].pixelColor.r, snakeFood[0].pixelColor.g, snakeFood[0].pixelColor.b); // display the food

  for (int i = 0; i < snakeGame.getSnakeLenght(); i++)
  {
    // Display the snake, my setpixel method has x=0, y=0 at the top left, but the library has it at bottom left, so I invert the Y-Axis:
    setPixel(snakeLimbs[i].posX, 8 - snakeLimbs[i].posY, snakeLimbs[i].pixelColor.r, snakeLimbs[i].pixelColor.g, snakeLimbs[i].pixelColor.b);
  }

  FastLED.show();
  snakeGame.tick(); // Main loop for the snake library

  if (snakeGame.wasGameReset()) // If the snake bit itself or the wall, flash a little
  {
    for (int i = 0; i < 30; i++)
    {
      changeRGBtoGBR();
      FastLED.show();
      delay(40);
    }
  }
}