#include <LiquidCrystal_I2C.h>
#include <AsyncTimer.h>

AsyncTimer t;


LiquidCrystal_I2C lcd(0x27, 20, 4); //initializing LCD (address, width, height)

bool condition = true;



void setup() {


  int buttonPin = 2;
  pinMode(buttonPin, INPUT);

  int dino_x = 1;







  lcd.init();
  lcd.backlight();


  uint8_t jizz4[8] = {

    0b00000,
    0b00000,
    0b00000,
    0b01010,
    0b01010,
    0b00100,
    0b00100,
    0b00000,
  };

  lcd.createChar(2, jizz4);


  uint8_t tree[8] = {
    0b00000,
    0b01110,
    0b10001,
    0b10101,
    0b10001,
    0b01110,
    0b00000,
    0b00000,

  };
  lcd.createChar(3, tree);

  uint8_t chare[8] = {
    0b00100,
    0b01110,
    0b01110,
    0b01110,
    0b01110,
    0b01110,
    0b11111,
    0b11011,

  };
  lcd.createChar(4, chare);

  uint8_t jizz1[8] = {

    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00100,
    0b00100,
  };

  lcd.createChar(5, jizz1);


  uint8_t jizz2[8] = {

    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b01010,
    0b01010,
    0b00100,
    0b00100,
  };

  lcd.createChar(6, jizz2);

  uint8_t jizz3[8] = {

    0b00000,
    0b00000,
    0b00000,
    0b01010,
    0b01010,
    0b00100,
    0b00100,
    0b00000,
  };

  lcd.createChar(7, jizz3);

};

void move_tree(int i, int s) {

  lcd.setCursor(i, 1);
  lcd.write(3);
  lcd.setCursor(s, 1);
  lcd.write(3);
  delay(150);
  lcd.setCursor(i, 1);
  lcd.print(" ");
  lcd.setCursor(s, 1);
  lcd.print(" ");

}

void move_dino(int BS, int x) {

  if (BS == 1) {
    lcd.setCursor(x, 1);
    lcd.print(" ");
    lcd.setCursor(x, 0);;
    lcd.write(4);
  }

  else if (BS == 0) {
    lcd.setCursor(x, 0);
    lcd.print(" ");
    lcd.setCursor(x, 1);
    lcd.write(4);
  }

}

void undo_dino() {
  int x = 1;

  lcd.setCursor(x, 0);
  lcd.print(" ");
  lcd.setCursor(x, 1);
  lcd.write(4);
  delay(10);


}

bool end_game(bool BS, int i, int s) {

  if ((BS == 0) && ((i == 1) || (s == 1))) {

    return false;

  }

  else {
    return true;
  }


}

int count_digits(int score) {

  int digits = 0; // this NEEDS to be zero othewisee the function starets using previous values
  // when called repetedly

  do {

    score = score / 10;
    ++digits;

  }

  while (score != 0);

  return digits;

}




void game() {

  int i = 16 ;
  int s = 24;
  bool BS;
  int x = 1;
  int points = 0;
  int digs = 0;
  long start = 0;
  long terminate = 0;
  long interval = 150;




  do {

    int buttonPin = 2;
    int buttonState = digitalRead(buttonPin);
    BS = buttonState;

    if (BS > 0) {
      start = millis();
    }



    digs = count_digits(points);
    lcd.setCursor((16 - digs), 0);
    lcd.print(points);

    move_dino(buttonState, x);


    move_tree(i, s);

    terminate = millis();

    if ((abs(terminate - start))> interval) {
      undo_dino();

    }


    i--;
    s--;

    if (i == 0) {
      i = random(16, 20);
      points++;
    }

    else if (s == 0) {
      s = random(20, 24);
      points++;

    }



  }

  while (end_game(BS, i, s));


}





void loop() {



  if (condition) {
    game();
  }

  condition = false;

  lcd.setCursor(1, 0);
  lcd.print(" ");
  lcd.setCursor(6, 0);
  lcd.print("GAME");
  lcd.setCursor(4, 1);
  lcd.print("ENDED");

  lcd.setCursor(1, 0);
  lcd.write(5);
  delay(400);

  lcd.setCursor(1, 0);
  lcd.write(6);
  delay(400);

  lcd.setCursor(1, 0);
  lcd.write(7);
  delay(400);


}


// THINGS TO DO YET:

// - **Write the score function.
// - **Write the function for the end game condition (aka when the tree and the dino collidde)
// - **Write the move_dino function
// - **Write the game function that calls the move_dino ands the move_tree function
// - Write the function for the max time the dino can stay in the air before it
//   starts falling down.
// - Make the move dino function buitton-press-time sensitive
// - correct the functions for two trees coming simullateneosuly so that they dont come
//   together.