// Function prototypes
void printOption(const char* label, int value1, int value2 = -1);

// Define constants
const int buttonPin = A0;

// shift register tl controll dice LEDs
const int dataPin = 2;   /* DS */
const int clockPin = 3;  /* SHCP */
const int latchPin = 4;  /* STCP */

// shift register to control the seven segment display
const int sevsegdataPin = 5;   /* DS */
const int sevsegclockPin = 6;  /* SHCP */
const int sevseglatchPin = 7;  /* STCP */

// refflects the pattern of the LED Dice
/*
2   1
5 4 3
7   6
*/

int dice [] = {
  0b00000000,
  0b00010000, // 1
  0b10000010, // 2
  0b10010010, // 3
  0b11000110, // 4
  0b11010110, // 5
  0b11101110, // 6
  0b11111111
};

int roundcounter = 0;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set button pin as input
  pinMode(buttonPin, INPUT);

  // set output pins for dice LED
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);

    // set output pins for seven segment display
  pinMode(sevsegdataPin, OUTPUT);
  pinMode(sevsegclockPin, OUTPUT);
  pinMode(sevseglatchPin, OUTPUT);


}



void loop() {
  // Check if the button is pressed
  if (digitalRead(buttonPin) == HIGH) {
    delay(50);
    while (digitalRead(buttonPin) == HIGH) {
      displayNumber(0);
      delay(50);
    }
    
    // Generate a random number between 1 and 6
    int yellow = random(1, 7);
    int red = random(1, 7);
    int green = random(1, 7);
    int blue = random(1, 7);
    int white0 = random(1, 7);
    int white1 = random(1, 7);

    // Display the random number using LEDs
    displayNumber(dice[white1]);
    displayNumber(dice[white0]);
    displayNumber(dice[blue]);
    displayNumber(dice[green]);
    displayNumber(dice[yellow]);
    displayNumber(dice[red]);


    // Print the random number in the console
    Serial.print("Red: ");
    Serial.print(red);
    Serial.print("   Yellow: ");
    Serial.print(yellow);
    Serial.print("   Green: ");
    Serial.print(green);
    Serial.print("   Blue: ");
    Serial.print(blue);
    Serial.print("   White 0: ");
    Serial.print(white0);
    Serial.print("   White 1: ");
    Serial.println(white1);
  // calculate possible combinations and print them 
  int white = white0 + white1;
 
  int yellow0 = white0 + yellow;
  int yellow1 = white1 + yellow;
 
  int blue0 = white0 + blue;
  int blue1 = white1 + blue;
 
  int red0 = white0 + red;
  int red1 = white1 + red;
 
  int green0 = white0 + green;
  int green1 = white1 + green;

  roundcounter++;

  Serial.print("======== Round: ");
  Serial.print(roundcounter);
  Serial.println(" ================");

  printOption("White", white);
  printOption("Yellow", yellow0, yellow1);
  printOption("Blue", blue0, blue1);
  printOption("Red", red0, red1);
  printOption("Green", green0, green1);

  Serial.println("================================");

  // display options on sevseg
  sevsegdisplayNumber(white);
  sevsegdisplayNumber(blue1);
  sevsegdisplayNumber(blue0);
  sevsegdisplayNumber(green1);
  sevsegdisplayNumber(green0);
  sevsegdisplayNumber(yellow1);
  sevsegdisplayNumber(yellow0);
  sevsegdisplayNumber(red1);
  sevsegdisplayNumber(red0);
  
  }
}

void displayNumber(int num) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, num);
  digitalWrite(latchPin, HIGH);
}

void printOption(const char* label, int value1, int value2 = -1) {
  Serial.print(label);
  Serial.print(": ");
  Serial.print(value1);
  if (value2 >= 0) {
    Serial.print(" / ");
    Serial.print(value2);
  }
  Serial.println();
}

void sevsegdisplayNumber(int num) {

    // Define the segment patterns for each digit (common cathode)
  const byte digitPatterns[] = {
  0b11000000,  // 0
  0b11111001,  // 1
  0b10100100,  // 2
  0b10110000,  // 3
  0b10011001,  // 4
  0b10010010,  // 5
  0b10000010,  // 6
  0b11111000,  // 7
  0b10000000,  // 8
  0b10011000   // 9
  };

  int tensDigit = num / 10;
  int onesDigit = num % 10;

  digitalWrite(sevseglatchPin, LOW);
  shiftOut(sevsegdataPin, sevsegclockPin, LSBFIRST, digitPatterns[onesDigit]);
    shiftOut(sevsegdataPin, sevsegclockPin, LSBFIRST, digitPatterns[tensDigit]);
  //shiftOut(sevsegdataPin, sevsegclockPin, LSBFIRST, );
  digitalWrite(sevseglatchPin, HIGH);
}
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595