#include <FVS.h>
//Memory_Shield
//LEDs und Taster müssen Invertiert werden, da gegen Masse geschaltet wird

#define BUTTON0 1
#define BUTTON1 5
#define BUTTON2 3
#define BUTTON3 4

#define MAXLEVEL 10

int buttons[] = { BUTTON0, BUTTON1, BUTTON2, BUTTON3 };
int state = 0;
int level = 0;

int musterVorgabe[MAXLEVEL] = {};
int musterEingabe[MAXLEVEL] = {};

void setup() {
  //alle LEDs löschen
  portMode(1, OUTPUT);
  portWrite(1, 0);
  //LEDs vom Shield ausschalten
  for (int i = 0; i < 4; i++) {
    digitalWrite(buttons[i], HIGH);
  }
  //Tft initialisieren
  Tft.begin();
  //Zufallszahl starten
  randomSeed(analogRead(39));
}

void loop() {
  switch (state) {
    case 0:  // neue Runde
      Tft.setCursorCharacter(1, 1);
      Tft.print("neue Runde in ");
      for (int j = 3; j > 0; j--) {
        Tft.setCursorCharacter(1, 15);
        Tft.print(String(j) + "  ");
        delay(1000);
      }
      level = 0;

      for (int i = 0; i < MAXLEVEL; i++) {
        musterVorgabe[i] = random(0, 4);
        musterEingabe[i] = -1;
      }
      state = 1;
      break;
    case 1:  // Ausgabe aktuelle Runde
      Tft.setCursorCharacter(1, 1);
      Tft.println("Ausgabe          ");
      Tft.print("                ");
      portMode(1, OUTPUT);
      for (int i = 0; i <= level; i++) {
        digitalWrite(buttons[musterVorgabe[i]], LOW);
        delay(500);
        digitalWrite(buttons[musterVorgabe[i]], HIGH);
        delay(500);
      }
      state = 2;
      break;
    case 2:  // Eingabe aktuelle Runde
             //GPIOs auf INPUT_PULLUP setzten und auf 0 abfragen!
      for (int b = 0; b < 4; b++) {
        pinMode(buttons[b], INPUT_PULLUP);
      }
      Tft.setCursorCharacter(1, 1);
      Tft.println("Eingabe        ");
      for (int i = 0; i <= level; i++) {
        while (musterEingabe[i] == -1) {
          for (int j = 0; j < 4; j++) {
            while (digitalRead(buttons[j]) == false) {
              musterEingabe[i] = j;
            }
          }
          delay(100);
        }
        Tft.print(".");
      }
      //Warte bis Vergleich, sieht besser aus wegen den Punkten
      delay(500);
      state = 3;
      break;
    case 3:  // Vergleich Eingabe/Ausgabe
      for (int i = 0; i <= level; i++) {
        if (musterEingabe[i] == musterVorgabe[i]) {
          state = 4;
        } else {
          state = 5;
          break;
        }
      }
      break;
    case 4:  // geschafft, Runde hochzählen und auf Display ausgeben
      //Muster zurücksetzen der Eingabe
      for (int i = 0; i < MAXLEVEL; i++) {
        musterEingabe[i] = -1;
      }
      level++;
      Tft.setCursorCharacter(4, 1);
      Tft.print("aktuelle Runde:" + String(level) +" ");
      state = 1;
      break;
    case 5:  // verloren
      Tft.setCursorCharacter(1, 1);
      Tft.print("leider verloren..");
      Tft.setCursorCharacter(1, 1);
      Tft.print("           ");
      Tft.setCursorCharacter(4, 1);
      Tft.print("                  ");
      Tft.setCursorCharacter(5, 1);
      Tft.print("letzter Rekord:" + String(level));
      delay(3000);
      state = 0;
      break;
  }
}