// Library Imports 

// Written by the IP-Team 13 
// E.S
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <SPI.h>
#include <MFRC522.h>

//Pin Definition

#define RST_PIN   9   // Pin für Reset beim RC522
#define SS_PIN    10  // Pin für Slave Select beim RC522

// Modul-Object Initiation 

MFRC522 mfrc522(SS_PIN, RST_PIN);
SoftwareSerial mySerial(16, 17);
DFRobotDFPlayerMini mp3;

// Setup

void setup() {

  // Start Serial Connection
  Serial.begin(115200);
  mySerial.begin(9600);
  SPI.begin();

  // Start Module Objects
  mfrc522.PCD_Init();

  // Check MP3-Module
  if (!mp3.begin(mySerial)) {
    while (true) {
      delay(0);
    }
  }

  // Set Volume 
  mp3.volume(30);

  // Check RC522
  Serial.println("Scan PICC to see UID, SAK, type, and data blocks...");
}


// Loop 

void loop() {

  // Define Variables
  uint8_t success;
  uint8_t uid[MFRC522::MF_KEY_SIZE];
  uint8_t uidLength;

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }

  // Read UID
  uidLength = mfrc522.uid.size;
  for (uint8_t i = 0; i < uidLength; i++) {
    uid[i] = mfrc522.uid.uidByte[i];
  }

  // Analyse Data 
  for (uint8_t block = 7; block < 8; block++) {
    byte data[18];
    byte dataSize = sizeof(data);
    success = mfrc522.MIFARE_Read(block, data, &dataSize);

    if (success) {
      // Get Hexadecimal Format
      String firstByteAsString = String(data[0], HEX);
      // Play Card Name
      playCardName(firstByteAsString);
    } 
    else {
      // Error Handling
      Serial.println("Read failed!");
    }
    Serial.println("");
  }

  // Reduction of Workload 
  delay(1000);
}

// Function : Handling Hexadecimal Format

void playCardName(String hexMod) {
  
  // Copy the String
  String kopie = hexMod;
  
  // Define Variables 
  int farbe, symbol;

  // Check the length of the String for leading zeros
  if (hexMod.length() == 1) {
    // Converting the Hexadecimal to a leading zero Format
    hexMod = String("00" + hexMod).substring(hexMod.length(), hexMod.length() + 2);
    // Setting the Color to Red 
    farbe = 0;
    // Get the Charakter for the Symbol
    int symbolChar = hexMod.charAt(1);

    // Check if the Symbol is one of the letters a to f
    if (symbolChar >= 'a' && symbolChar <= 'f') {
      // Calculate the decimal number for the letters from a to f
      symbol = 10 + (symbolChar - 'a');
    } else {
      // Calculate the Decimal Number of the Hexadecimal Number
      symbol = hexMod.charAt(1)-'0';
    }
  } 
  else {
    farbe = hexMod.substring(0, 1).toInt();
    int symbolChar = hexMod.charAt(1);

    // Check if the Symbol is a letter between a and f
    if (symbolChar >= 'a' && symbolChar <= 'f') {
      symbol = 10 + (symbolChar - 'a');
    } else {
      symbol = hexMod.substring(1, 2).toInt();
    }
  }

  // Play the Corresponding Audiofile from the Storage
  playCard(farbe, symbol);
}

// Function: Playing the corresponding Audiofile for the Cardname

void playCard(int farbNummer, int symbolNummer) {
  
  // First Switch : Check the Color 
  switch (farbNummer) {
    case 0: mp3.play(16); break; // Red
    case 1: mp3.play(17); break; // Yellow
    case 2: mp3.play(18); break; // Blue
    case 3: mp3.play(19); break; // Green
    case 4: mp3.play(20); break; // black
  }

  // Wait 2 Seconds to avoid Latency or Noises of the File
  delay(2000);

  // Switch 2: Check the Symbol 
  switch (symbolNummer) {
    case 0: mp3.play(1);  break; // Zero
    case 1: mp3.play(2);  break; // One
    case 2: mp3.play(3);  break; // Two 
    case 3: mp3.play(4);  break; // Three
    case 4: mp3.play(5);  break; // Four
    case 5: mp3.play(6);  break; // Five 
    case 6: mp3.play(7);  break; // Six
    case 7: mp3.play(8);  break; // Seven
    case 8: mp3.play(9);  break; // Eight
    case 9: mp3.play(10); break; // Nine
    case 10: mp3.play(11); break; // Skip
    case 11: mp3.play(12); break; // Reverse 
    case 12: mp3.play(13); break; // Draw 2
    case 13: mp3.play(15); break; // Draw 4
    case 14: mp3.play(14); break; // Color Change
  }

  // Wait 1 Second to avoid noises and latency
  delay(1000);
}
