/*
 * BadgeClone — Kaihatsu Lab
 * Lecteur RFID RC522 13.56MHz
 * Sauvegarde UID sur carte microSD, affichage OLED, LED RGB de statut
 */

#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h>

#define RC522_SCK   18
#define RC522_MOSI  23
#define RC522_MISO  19
#define RC522_CS    5
#define RC522_RST   27
#define SD_CS       4
#define OLED_SDA    21
#define OLED_SCL    22
#define SCREEN_W    128
#define SCREEN_H    64
#define LED_R       33
#define LED_G       32
#define LED_B       14
#define BTN_MODE    26

MFRC522 rfid(RC522_CS, RC522_RST);
Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire, -1);
Preferences prefs;

unsigned long btnPressStart = 0;
bool btnHeld = false;
const unsigned long LONG_PRESS_MS = 800;
String lastUID = "";
int savedCount = 0;

void setLED(bool r, bool g, bool b) {
  digitalWrite(LED_R, r ? HIGH : LOW);
  digitalWrite(LED_G, g ? HIGH : LOW);
  digitalWrite(LED_B, b ? HIGH : LOW);
}
void selectRC522() { digitalWrite(SD_CS, HIGH); digitalWrite(RC522_CS, LOW); }
void selectSD() { digitalWrite(RC522_CS, HIGH); digitalWrite(SD_CS, LOW); }
void deselectAll() { digitalWrite(RC522_CS, HIGH); digitalWrite(SD_CS, HIGH); }

void updateDisplay(String status) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Mode: 13.56 MHz");
  display.println("----------------");
  display.println(status);
  display.print("Slots: "); display.println(savedCount);
  display.display();
}

void saveUIDToSD(String uid) {
  selectSD();
  File f = SD.open("/uid_log.csv", FILE_APPEND);
  if (f) { f.println(uid); f.close(); savedCount++; }
  deselectAll();
}

void readRC522() {
  selectRC522();
  if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    String uid = "";
    for (byte i = 0; i < rfid.uid.size; i++) {
      if (rfid.uid.uidByte[i] < 0x10) uid += "0";
      uid += String(rfid.uid.uidByte[i], HEX);
    }
    uid.toUpperCase();
    lastUID = uid;
    setLED(false, true, false);
    updateDisplay("UID: " + uid);
    rfid.PICC_HaltA();
    rfid.PCD_StopCrypto1();
  }
  deselectAll();
}

void handleButton() {
  bool pressed = (digitalRead(BTN_MODE) == LOW);
  if (pressed && !btnHeld) { btnHeld = true; btnPressStart = millis(); }
  else if (!pressed && btnHeld) {
    btnHeld = false;
    unsigned long held = millis() - btnPressStart;
    if (held >= LONG_PRESS_MS) {
      if (lastUID.length() > 0) {
        setLED(false, false, true);
        saveUIDToSD(lastUID);
        prefs.putString(("slot" + String(savedCount)).c_str(), lastUID);
        updateDisplay("Sauvegarde: " + lastUID);
        delay(400);
      }
    } else {
      updateDisplay("RC522 actif");
    }
    delay(150); setLED(false, false, false);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RC522_CS, OUTPUT); pinMode(SD_CS, OUTPUT); deselectAll();
  pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT);
  setLED(false, false, false);
  pinMode(BTN_MODE, INPUT_PULLUP);
  SPI.begin(RC522_SCK, RC522_MISO, RC522_MOSI, RC522_CS);
  selectRC522(); rfid.PCD_Init(); deselectAll();
  selectSD();
  if (!SD.begin(SD_CS)) Serial.println("Erreur: carte SD non detectee");
  deselectAll();
  Wire.begin(OLED_SDA, OLED_SCL);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("Erreur: OLED non detecte");
  prefs.begin("badgeclone", false);
  savedCount = prefs.getInt("count", 0);
  updateDisplay("Pret");
}

void loop() {
  handleButton();
  readRC522();
}