// Inicializace knihoven

#include <Wire.h>
#include <Adafruit_MPR121.h>
#include <EEPROM.h>

// Definování výstupních pinů z Arduina

#define start_f 22  // První pin k bázi tranzistoru LED bloku
#define end_f 42    // Poslední pin k bázi tranzistoru LED bloku

#define red 2       // Výstupní pin k bázi tranzistoru pro aktivaci červené barvy
String ver = "v.1.0_release";

#define green 3     // Výstupní pin k bázi tranzistoru pro aktivaci zelené barvy

#ifndef _BV
#define _BV(bit) (1 << (bit))
#endif

#define EColour 1

byte colour;

int points = 0;
const int mainTime = 30 * 1000; //s

unsigned int gameStartTime;

unsigned int brightGreen = 255;
unsigned int brightRed = 255;

Adafruit_MPR121 cap = Adafruit_MPR121();
Adafruit_MPR121 cap2 = Adafruit_MPR121();

int ledField[20];

int actualLeds[4];

int randomNum = 0;
bool pass = false;

bool grun = false;
bool set = false;
bool deb = false;

unsigned long lastTime;

bool coldstart = true;

String serial;

int TP;

uint16_t lasttouched = 0;
uint16_t currtouched = 0;

//funkce LE Diod

void ledHigh(int place) {
  setColour();
  digitalWrite(place, HIGH);
  Serial.print(place);
  Serial.println("ON");
}

void ledLow(int place) {
  digitalWrite(place, LOW);
  Serial.print(place);
  Serial.println("OFF");
}

void setColour() {
  if (colour == 2) {
    digitalWrite(red, HIGH);
    digitalWrite(green, LOW);
    Serial.println("red");
  } else if (colour == 1) {
    digitalWrite(red, LOW);
    digitalWrite(green, HIGH);
    Serial.println("green");
  }
}

//click check

bool clickCheck(int pozice) {
  //driver1
  bool checkfield [10];
  for (int i = 1; i <= 10; i++) {
    checkfield[i - 1] = false;
    currtouched = cap.touched();
  }
  for (uint8_t i = 1; i <= 10; i++) {
    if ((currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) {
      checkfield[i - 1] = true;
    }
  }
  //driver2
  bool checkfield2 [10];
  for (int i = 1; i <= 10; i++) {
    checkfield2[i - 1] = false;
    currtouched = cap2.touched();
  }

  for (uint8_t i = 1; i <= 10; i++) {
    // it if *is* touched and *wasnt* touched before, alert!
    if ((currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) {
      checkfield2[i - 1] = true;
    }
  }
  /*  for (int i = 0; i <= 9; i++) {
      if (checkfield2[i] == true) {
        Serial.print("true ");
      } else {
        Serial.print("false ");
      }
    }
    Serial.println(); */
  //Primarni checkfield
  bool maincheck[20];
  for (int i = 0; i <= 9; i++) {
    maincheck[i] = checkfield[i];
    maincheck[i + 10] = checkfield2[i];
  }
  /*  for (int i = 0; i <= 19; i++) {
      if (maincheck[i] == true) {
        Serial.print("true ");
      } else {
        Serial.print("false ");
      }
    }
    Serial.println();
    delay(1000); */
  if (maincheck[pozice - start_f] == true) {
    Serial.println("check true");
    return true;
  } else {
    //    Serial.println("check false");
    return false;
  }
}

//komunikace s displayem

void dislplaySendScore (int input) {
  String Send = "t11.txt=\"";
  Send += input;
  Send += "\"";
  Serial1.print(Send);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);
}

void displaySendTime () {
  int endTime = mainTime - gameTime();
  endTime = endTime / 1000;
  String Send = "t10.txt=\"";
  Send += endTime;
  Send += "\"";
  Serial1.print(Send);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);
}

//aktualni cas hry

int gameTime() {
  return (millis() - gameStartTime); //parek s jogurtem
}

//hra

void game() {
  Serial.println("game call");
  do {
    Serial.println("game start");
    while (grun) {
      displaySendTime ();
      if (clickCheck(randomNum) == true) {
        pass = true;
        points++;
        dislplaySendScore (points);
      } else {
        pass = false;
      }
      if (pass || coldstart) {
        ledLow(randomNum);
        randomNum = random(start_f, end_f);
        ledHigh(randomNum);
        pass = false;
        if (coldstart) {
          coldstart = false;
          Serial.println("coldstart deactive");
        }
      }
      if (gameTime() >= mainTime) {
        grun = false;
        //odeslani do displaye hlasky o konci hry
        Serial1.print("t13.txt=\"Konec hry\"");
        Serial1.write(0xff);
        Serial1.write(0xff);
        Serial1.write(0xff);
        coldstart = true;
        ledLow(randomNum);
        points = 0;
      }
      if (Serial1.available()) {
        Serial.println("String v prubehu hry");
        serial = Serial1.readString();
        delay(50);
        Serial.println(serial);
        if (serial.indexOf("pkonec") >= 0) {
          Serial.println("konec");
          grun = false;
          coldstart = true;
          ledLow(randomNum);
          points = 0;
        } else {
          Serial.println("chybadef");
        }
      }
    }
  } while (grun);
}

//Nastavení

void settings() {
  for (int i = 24; i <= 39; i = i + 5) {
    ledHigh(i);
  }
  do {
    if (Serial1.available()) {
      serial = Serial1.readString();
      if (serial.indexOf("pz") >= 0) {
        EEPROM.update(EColour, 1);
        colour = EEPROM.read(EColour);
        for (int i = 24; i <= 39; i = i + 5) {
          ledHigh(i);
        }
      } else if (serial.indexOf("pc") >= 0) {
        EEPROM.update(EColour, 2);
        colour = EEPROM.read(EColour);
        for (int i = 24; i <= 39; i = i + 5) {
          ledHigh(i);
        }
      } else if (serial.indexOf("psetend")) {
        for (int i = 24; i <= 39; i = i + 5) {
          ledLow(i);
        }
        set = false;
        Serial.println("Settings end");
      }
    }
  } while (set == true);
}

//Debuging

void debug() {
  lastTime = millis();
  do {
    if (millis() - lastTime > 400) {
      for (int loc = start_f + TP; loc <= end_f; loc = loc + 5) {
        ledLow(loc);
      }
      TP++;
      if (TP > 4) {
        TP = 0;
      }
      for (int loc = start_f + TP; loc <= end_f; loc = loc + 5) {
        ledHigh(loc);
      }
      lastTime = millis();
    }
    if (Serial1.available()) {
      Serial.println("readStart");
      serial = Serial1.readString();
      Serial.println(serial);
      if (serial.indexOf("ver") >= 0) {
        Serial.println("odesilam data sestaveni");
        String Send = "t2.txt=\"";
        Send += ver;
        Send += "\"";
        Serial1.print(Send);
        Serial1.write(0xff);
        Serial1.write(0xff);
        Serial1.write(0xff);
      } else if (serial.indexOf("debugend") >= 0) {
        deb = false;
        for (int loc = start_f; loc <= end_f; loc++) {
          ledLow(loc);
        }
        Serial.println("Debugging end");
      }
    }
  } while (deb == true);
}

void setup() {
  Serial.begin(57600);
  Serial1.begin(9600);
  randomNum = random(start_f, end_f);
  for (int i = start_f; i <= end_f; i++) {
    pinMode(i, OUTPUT);
  }
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  cap.begin(0x5A);
  cap2.begin(0x5C);

  for (int loc = 0; loc <= 19; loc++) {
    ledField[loc] = loc;
  }

  colour = EEPROM.read(EColour);
  Serial.println("Setup OK");

}

void loop() {
  if (Serial1.available()) {
    Serial.println("ReadStart");
    String serial = Serial1.readString();
    Serial.println(serial);
    if (serial.indexOf("pstart") >= 0) {
      Serial.println("start");
      grun = true;
      dislplaySendScore (points);
      displaySendTime();
      gameStartTime = millis();
      game();
    } else if (serial.indexOf("pset") >= 0) {
      Serial.println("settings");
      set = true;
      settings();
    } else if (serial.indexOf("pdebug") >= 0) {
      Serial.println("debugging");
      deb = true;
      debug();
    }
  }
}