// Reaction Time Game Code
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>



// Uncomment according to your hardware type
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW



// Defining size, and output pins
#define MAX_DEVICES 4
#define CS_PIN 10



// Create a new instance of the MD_Parola class with hardware SPI connection
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);



// Reaction Time Game Code



const int pushButtonPin = 2; // Pin for the push button
const int ledPin = 4; // Pin for the LED
const int ldrPin = A0; // Analog pin for the LDR



unsigned long startTime; // Variable to store the start time
unsigned long endTime; // Variable to store the end time
unsigned long reactionTime; // Variable to store reaction time
unsigned long recentScores[5]; // Array to store the last 5 scores
int scoreCount = 0; // Counter for scores



String sc1, sc2, sc3, sc4, sc5; // Variables for recent scores in string form



void setup() {
  pinMode(pushButtonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(9600);
  resetScores(); // Initialize recent scores with 0



  // // Intialize the object
  myDisplay.begin();



  // Set the intensity (brightness) of the display (0-15)
  myDisplay.setIntensity(0);



  // Clear the display
  myDisplay.displayClear();



  myDisplay.displayScroll("Hello", PA_CENTER, PA_SCROLL_LEFT, 100);
}



void loop() {
  if (digitalRead(pushButtonPin) == LOW) { // Wait for button press
    delay(50); // Debounce delay
    while (digitalRead(pushButtonPin) == LOW); // Wait for button release
    delay(7000);
    // Step 1: Flash the LED twice
    for (int i = 0; i < 2; i++) {
      digitalWrite(ledPin, HIGH);
      delay(250);
      digitalWrite(ledPin, LOW);
      delay(250);
    }



    //repeat steps 2 to 5
    for (int round = 1; round <= 5; round++) {
      Serial.print ("Round: ");
      Serial.println(round);



      // Step 2: Print "GET READY" and wait 10 seconds
      myDisplay.setTextAlignment(PA_CENTER);
      myDisplay.print("GET");
      delay(600);
      myDisplay.print("READY");
      Serial.println("GET READY");
      long int Delay = random(5000, 10000);
      delay(Delay);



      // Step 3: Turn on the LED and print "FIRE"
      digitalWrite(ledPin, HIGH);
      Serial.println("FIRE");
      myDisplay.setTextAlignment(PA_CENTER);
      myDisplay.print("FIRE");
      startTime = millis();



      // Step 4: Monitor the LDR for a hit or timeout
      bool hit = false;
      while (millis() - startTime <= 5000) { // 5-second window
        int ldrValue = analogRead(ldrPin);
        if (ldrValue > 75) { // Laser detected
          hit = true;
          break;
        }
      }



      digitalWrite(ledPin, LOW); // Turn off the LED



      if (hit) {
        endTime = millis();
        for (int i = 0; i < 3; i++) {
          digitalWrite(ledPin, HIGH);
          delay(250);
          digitalWrite(ledPin, LOW);
          delay(250);
        }
        reactionTime = endTime - startTime;
        Serial.print("Reaction Time: ");
        Serial.print(reactionTime);
        Serial.println(" ms");
        addScore(reactionTime);
        myDisplay.setTextAlignment(PA_RIGHT);
        myDisplay.print(String(reactionTime));
        delay(3000);
        updateScoreStrings();



      } else {
        myDisplay.setTextAlignment(PA_CENTER);
        myDisplay.print("MISS");
        Serial.println("Miss");



        delay(3000);
      }
      // result show time adjust (hit or miss)
      delay(5000);
    }



    // Step 5: Print recent scores sorted in descending order
    printScores();
    DisplayDot ();
  }



}



void resetScores() {
  for (int i = 0; i < 5; i++) {
    recentScores[i] = 0;
  }
  updateScoreStrings();
}



void addScore(unsigned long newScore) {
  if (scoreCount < 5) {
    recentScores[scoreCount++] = newScore;
  } else {
    for (int i = 1; i < 5; i++) {
      recentScores[i - 1] = recentScores[i];
    }
    recentScores[4] = newScore;
  }
  sortScores();
  updateScoreStrings();
}



void sortScores() {
  for (int i = 0; i < scoreCount - 1; i++) {
    for (int j = i + 1; j < scoreCount; j++) {
      if (recentScores[i] > recentScores[j]) { // Sort descending
        unsigned long temp = recentScores[i];
        recentScores[i] = recentScores[j];
        recentScores[j] = temp;
      }
    }
  }
}



void printScores() {
  Serial.println("Recent Scores:");
  for (int i = 0; i < scoreCount; i++) {
    Serial.print(i + 1);
    Serial.print(". ");
    Serial.print(recentScores[i]);
    Serial.println(" ms");
  }
}



void updateScoreStrings() {
  sc1 = (scoreCount > 0) ? String(recentScores[0]) : "" ; //+ " ms" : "N/A";
  sc2 = (scoreCount > 1) ? String(recentScores[1]) : ""; //+ " ms" : "N/A";
  sc3 = (scoreCount > 2) ? String(recentScores[2]) : ""; //+ " ms" : "N/A";
  sc4 = (scoreCount > 3) ? String(recentScores[3]) : ""; //+ " ms" : "N/A";
  sc5 = (scoreCount > 4) ? String(recentScores[4]) : ""; //+ " ms" : "N/A";



}
// void DisplayDot (){
// myDisplay.displayClear();
// String ST = "S1:" + String(sc1) + "S2:" + String(sc2) + "S3:" + String(sc3) + "S4:" + String(sc4) + "S5:" + String(sc5);
// myDisplay.setTextAlignment(PA_LEFT);
// myDisplay.print(ST);



// //myDisplay.displayScroll(ST, PA_CENTER, PA_SCROLL_LEFT, 100);



// // if (myDisplay.displayAnimate()) {
// // myDisplay.displayReset();
// // }
// }
void DisplayDot() {
  myDisplay.displayClear();
  String ST = " 1st " + sc1 + " 2nd " + sc2 + " 3rd " + sc3 + " 4th " + sc4 + " 5th " + sc5;



  // Convert String to char array
  char scrollText[ST.length() + 1];
  ST.toCharArray(scrollText, ST.length() + 1);



  // Set the scrolling parameters
  myDisplay.displayScroll(scrollText, PA_CENTER, PA_SCROLL_LEFT, 100);



  // Animate the scroll until complete
  while (!myDisplay.displayAnimate()) {
    // Continuously update the animation
  }
}