// Include the binocular AI sensor library
#include "DFRobot_AI10.h"
// Include the speech synthesis library
#include "DFRobot_SpeechSynthesis_V2.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Include the LCD display library
#include "DFRobot_LcdDisplay.h"

// Set up the LCD screen with its I2C address
DFRobot_Lcd_IIC lcd(&Wire, /*I2CAddr*/ 0x2c);

// Variables for display elements
uint8_t iconId;
uint8_t gificonId;
uint8_t pictureId;

// Speech synthesis object
DFRobot_SpeechSynthesis_I2C ss;

// Relay pin for the electromagnetic lock
int Relay = 13;

// Set up the AI sensor based on the board type
#if defined(ARDUINO_AVR_UNO) || defined(ESP8266)
  SoftwareSerial mySerial(4, 5);  // UART pins 4 (RX) and 5 (TX)
  DFRobot_AI10_UART recognize(&mySerial, 115200);  // 115200 baud rate
#elif defined(ESP32)
  DFRobot_AI10_UART recognize(&Serial1, 115200, /*rxD2*/25, /*txD3*/26);
#else
  DFRobot_AI10_UART recognize(&Serial1, 115200);
#endif


void setup() {
  // Start serial communication
  Serial.begin(115200);
  
  // Set up the electromagnetic lock
  pinMode(6, INPUT_PULLUP);  // Pin 6 as input with pull-up resistor
  pinMode(Relay, OUTPUT);    // Relay pin as output
  
  // Initialize the LCD screen
  lcd.begin();
  lcd.cleanScreen();         // Clear the screen
  delay(500);                // Wait a bit
  lcd.setBackgroundColor(WHITE);  // Set white background

  // Wait for serial port to be ready
  while (!Serial);
  
  // Connect to the AI sensor
  while(!recognize.begin()){
    Serial.println("Can't find the device!");
    delay(1000);  // Try again after 1 second
  }
  Serial.println("Device connected!");

  // Turn on face detection mode
  if(recognize.enableFaceFrame()){
    Serial.println("Face detection activated!");
  }
  
  // Show welcome screen and message
  ss.begin();                      // Start speech module
  digitalWrite(Relay, LOW);        // Make sure lock is closed initially
  pictureId = lcd.drawIcon(0, 0, "wel.png", 256);  // Display welcome image
  ss.speak(F("Welcome Home"));     // Say welcome message
  delay(2000);                     // Show for 2 seconds
}

void loop() {
  // Variable to store recognition results
  sRecognitionData_t recDat;

  /* 
   * Start continuous recognition:
   * - Automatically detects faces and starts recognition
   * - Stops after 1 second if no one is detected
   * - Timeout can be set between 3-20 seconds
   */
  recDat = recognize.startContinuousFaceRecognition(/*timeout*/1);

  // Check if recognition was successful
  if(recDat.result == eSuccess){
    Serial.println("Recognition worked!");
    ss.speak(F("Recognition successful"));  // Announce success
    
    // Show what was recognized (face or palm)
    Serial.print("Recognized: ");
    Serial.println(recDat.type == eFace ? "Face" : "Palm");
    Serial.print("User ID: ");
    Serial.println(recDat.userData.UID);

    // Show corresponding image based on recognition type
    if(recDat.type == eFace){
      Serial.println("It's a face!");
      ss.speak(F("Face recognized"));
      digitalWrite(Relay, HIGH);  // Unlock the box
      lcd.updateIcon(pictureId, 0, 0, "face.png", 256);  // Show face image
    } else {
      Serial.println("It's a palm!");
      ss.speak(F("Palm recognized"));
      digitalWrite(Relay, HIGH);  // Unlock the box
      lcd.updateIcon(pictureId, 0, 0, "palm.png", 256);  // Show palm image
    }

    // Show unlock screen and message
    ss.speak(F("Unlocked"));
    lcd.updateIcon(pictureId, 0, 0, "unlock.png", 256);  // Show unlocked image
    delay(2000);  // Keep unlocked for 2 seconds
    
    // Lock again and update display
    ss.speak(F("Locked"));
    lcd.updateIcon(pictureId, 0, 0, "lock.png", 256);  // Show locked image
    digitalWrite(Relay, LOW);  // Lock the box
    delay(2000);
    
  } else {
    // If nothing was recognized, show scanning message
    Serial.println("Scanning...");
    lcd.updateIcon(pictureId, 0, 0, "reco.png", 256);  // Show scanning image
    delay(1000);  // Check again after 1 second
  }
}
