#include <Keypad.h>
#include <TM1637Display.h>
// Definities voor display pinnen
#define CLK1 22 // Gewijzigde pin voor het eerste display
#define DIO1 23 // Gewijzigde pin voor het eerste display
#define CLK2 21 // Gewijzigde pin voor het tweede display
#define DIO2 19 // Gewijzigde pin voor het tweede display
// Definities voor rotary encoder en knoppen
#define ROTARY_PIN1 26 // Gewijzigde pin voor rotary encoder
#define ROTARY_PIN2 27 // Gewijzigde pin voor rotary encoder
#define ROTARY_BUTTON 25 // Gewijzigde pin voor rotary button
// Definities voor debounce tijden
#define DEBOUNCE_DELAY 200
#define RESET_DEBOUNCE_DELAY 100
// Initialisatie van display modules
TM1637Display display1(CLK1, DIO1);
TM1637Display display2(CLK2, DIO2);
// Keypad configuratie
const byte ROWS = 4; 
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {16, 17, 18, 0}; // Specifieke pinnen voor de rijen
byte colPins[COLS] = {2, 4, 5, 15}; // Specifieke pinnen voor de kolommen
// Initialisatie van het keypad
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
int lastEncoded = 0;
unsigned long lastDebounceTime = 0;
int availableScores[] = {201, 301, 401, 501, 601, 701, 801, 901};
int playerScores[2] = {0, 0};
int scoreIndex = 3;
bool scoreLocked = false;
int currentPlayer = 1;
String currentInput = "";
int previousScore = 0; // Opslaan van de laatst ingevoerde score voor undo-functie
int lastPlayer = 0; // Bijhouden van de laatste speler die scoorde
void handleRotaryEncoder() {
  if (scoreLocked) return;
  int MSB = digitalRead(ROTARY_PIN1);
  int LSB = digitalRead(ROTARY_PIN2);
  int currentEncoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | currentEncoded;
  unsigned long currentTime = millis();
  if (currentTime - lastDebounceTime > DEBOUNCE_DELAY) {
    if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
      scoreIndex = min(scoreIndex + 1, (int)(sizeof(availableScores) / sizeof(availableScores[0]) - 1));
      display1.showNumberDec(availableScores[scoreIndex], false);
      lastDebounceTime = currentTime;
    } else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
      scoreIndex = max(scoreIndex - 1, 0);
      display1.showNumberDec(availableScores[scoreIndex], false);
      lastDebounceTime = currentTime;
    }
  }
  lastEncoded = currentEncoded;
}
void handleButtonPress() {
  bool buttonState = digitalRead(ROTARY_BUTTON) == LOW;
  if (buttonState && !scoreLocked && millis() - lastDebounceTime > DEBOUNCE_DELAY) {
    scoreLocked = true;
    playerScores[0] = availableScores[scoreIndex];
    playerScores[1] = availableScores[scoreIndex];
    currentPlayer = 1;
    updateDisplays();
    lastDebounceTime = millis();
  }
}
void handleKeypad() {
  if (!scoreLocked) return;
  char key = customKeypad.getKey();
  if (key) {
    if (key == 'A') {  // Gebruik A knop als reset
      scoreIndex = 3;
      scoreLocked = false;
      display1.showNumberDec(availableScores[scoreIndex], false);
      display2.clear();
    } else if (key == 'B') {  // Gebruik B knop om laatste score te annuleren
      playerScores[lastPlayer - 1] += previousScore;
      currentPlayer = lastPlayer;  // Ga verder met dezelfde speler
      updateDisplays();
    } else if (key == '#') {
      if (currentInput.length() > 0) {
        int score = currentInput.toInt();
        previousScore = score;  // Sla de laatst ingevoerde score op
        lastPlayer = currentPlayer; // Onthoud welke speler scoorde
        playerScores[currentPlayer - 1] -= score;
        currentInput = "";
        currentPlayer = currentPlayer % 2 + 1; // Wissel van speler
        updateDisplays();
      }
    } else if (isdigit(key)) {
      currentInput += key;
      displayCurrentInput();
    }
  }
}
uint8_t* getDigitSegments(int num) {
    static uint8_t segData[4];
    for (int i = 0; i < 4; i++) {
        segData[i] = 0;
    }
    int digitPos = 3;
    do {
        segData[digitPos--] = display1.encodeDigit(num % 10);
        num /= 10;
    } while (num > 0 && digitPos >= 0);
    return segData;
}
void updateDisplays() {
    uint8_t segPlayer1[4] = {0x00, 0x00, 0x00, 0x00};
    uint8_t segPlayer2[4] = {0x00, 0x00, 0x00, 0x00};
    memcpy(segPlayer1, getDigitSegments(playerScores[0]), 4);
    memcpy(segPlayer2, getDigitSegments(playerScores[1]), 4);
    if (currentPlayer == 1) {
        segPlayer1[0] |= 0x40; // Voeg streepje toe bij speler 1
    } else {
        segPlayer2[0] |= 0x40; // Voeg streepje toe bij speler 2
    }
    display1.setSegments(segPlayer1);
    display2.setSegments(segPlayer2);
}
void displayCurrentInput() {
    uint8_t segData[4] = {0x00, 0x00, 0x00, 0x00};
    memcpy(segData, getDigitSegments(currentInput.toInt()), 4);
    if (currentPlayer == 1) {
        display1.setSegments(segData);
    } else {
        display2.setSegments(segData);
    }
}
void setup() {
  Serial.begin(9600);
  pinMode(ROTARY_PIN1, INPUT_PULLUP);
  pinMode(ROTARY_PIN2, INPUT_PULLUP);
  pinMode(ROTARY_BUTTON, INPUT_PULLUP);
  display1.setBrightness(0x0f);
  display2.setBrightness(0x0f);
  display1.showNumberDec(availableScores[scoreIndex], false);
  display2.clear();
}
void loop() {
  if (!scoreLocked) {
    handleRotaryEncoder();
  }
  handleButtonPress();
  handleKeypad();
}