#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

// Define the time to wait between iterations in the loop (in milliseconds)
const uint16_t WAIT_TIME = 1000;

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4

#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    53

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

// Define pin numbers for various components
#define IR 3      // Digital Input of the IR sensor module, set the sensitivity using on-board potentiometer, don´t forget to connect +5V and GND
#define COIN 2    // Coin pin of the acceptor is connected to D2 and via 10k resistor to 5v
                  // Grounds of coin acceptor and arduino are connected
                  // Coin acceptor is connected to external 12v power supply
                  // Arduino Uno is powered by +5V
#define BUBBLE 4

// Variables used to measure the intervals between impulses
int i = 0; // The number of loop iterations between impulses
int impulsCount = 0; // Number of impulses detected
unsigned long total_amount = 0; // Sum of all the coins inserted

unsigned long timerFrom; // A variable to keep track of time for bubble display

bool enableRelay; // A flag to enable/disable bubble display

void setup(void)
{
  P.begin(); // Initialize the LED matrix display
  Serial.begin(9600); // Initialize the serial communication for debugging
  attachInterrupt(digitalPinToInterrupt(COIN), incomingImpuls, FALLING); // Attach the interrupt for coin detection
  pinMode(IR, INPUT); // Set IR sensor pin as input
  pinMode(COIN, INPUT); // Set coin sensor pin as input
  pinMode(BUBBLE, INPUT); // Set bubble sensor pin as input

  P.print("  0:00"); // Display initial time on the LED matrix
}

void loop(void)
{
  i = i + 1; // Increment the loop counter

  // Print debug information to the serial monitor
  Serial.print("i=");
  Serial.print(i);
  Serial.print(" Impulses:");
  Serial.print(impulsCount);
  Serial.print(" Total:");
  Serial.println(total_amount);

  // If total_amount is greater than 0 and the IR sensor is active, enable bubble display
  if (!enableRelay && total_amount > 0 && digitalRead(IR) == true) {
    Serial.println("ENABLED");
    enableRelay = true;
    digitalWrite(BUBBLE, HIGH); // Turn on the bubble display
    timerFrom = millis(); // Record the current time
  }

  // If bubble display is enabled and the time has elapsed, disable bubble relay
  if (enableRelay && timerFrom + total_amount < millis()) {
    Serial.println("DISABLED");
    enableRelay = false;
    total_amount = 0;   // Reset the inserted money timer
    digitalWrite(BUBBLE, LOW); // Turn off the bubble display
  }

  // If bubble display is enabled, calculate the remaining time in minutes and seconds
  if (enableRelay) {
    int seconds = ((timerFrom - millis()) + total_amount) / 1000; // Calculate remaining time and covert it to seconds
    int minutes = 0; // Initialize minutes to 0

    // Convert seconds to minutes if it exceeds 60 seconds
    while (seconds > 60) {
      minutes++;
      seconds = seconds - 60;
    }

    // Create a formatted time string in the format "  mm:ss"
    String time;
    if (seconds < 10) // Add a leading zero for single-digit seconds
      time = "  " + String(minutes) + ":0" + String(seconds);
    else
      time = "  " + String(minutes) + ":" + String(seconds);

    P.print(time); // Display the time on the LED matrix
  }
  else {
    int seconds = total_amount / 1000; // Convert total_amount (in milliseconds) to seconds
    int minutes = 0; // Initialize minutes to 0

    // Convert seconds to minutes if it exceeds 60 seconds
    while (seconds > 60) {
      minutes++;
      seconds = seconds - 60;
    }

    // Create a formatted time string in the format "  mm:ss"
    String time;
    if (seconds < 10) // Add a leading zero for single-digit seconds
      time = "  " + String(minutes) + ":0" + String(seconds);
    else
      time = "  " + String(minutes) + ":" + String(seconds);

    P.print(time); // Display the time on the LED matrix
  }

  // If i is greater than or equal to 30 (approximately 1 second) and impulsCount matches a specific value, add the corresponding coin amount to total_amount and enable bubble display
  if (i >= 30 && impulsCount == 1) {
    Serial.println("1 penny");
    total_amount = total_amount + 1000; // Add 1 penny (1000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  } else if (i >= 30 && impulsCount == 2) {
    Serial.println("5 penny");
    total_amount = total_amount + 5000; // Add 5 penny (5000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  } else if (i >= 30 && impulsCount == 3) {
    Serial.println("10 penny");
    total_amount = total_amount + 10000; // Add 10 penny (10000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  } else if (i >= 30 && impulsCount == 4) {
    Serial.println("25 penny");
    total_amount = total_amount + 25000; // Add 25 penny (25000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  } else if (i >= 30 && impulsCount == 5) {
    Serial.println("50 penny");
    total_amount = total_amount + 50000; // Add 50 penny (50000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  } else if (i >= 30 && impulsCount >= 6) {
    Serial.println("1 dollar");
    total_amount = total_amount + 100000; // Add 1 dollar (100000 milliseconds) to total_amount
    impulsCount = 0; // Reset impulsCount
  }
}

// Interrupt service routine for coin detection
void incomingImpuls()
{
  impulsCount = impulsCount + 1; // Increment impulsCount when a coin is detected
  i = 0; // Reset the loop counter to measure intervals between impulses
}
NOCOMNCVCCGNDINLED1PWRRelay Module