#include Wire.h>
#include LiquidCrystal_I2C.h>
#include ESP32Servo.h>

// LCD I2C address: commonly 0x27 or 0x3F
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Servo
Servo lightningServo;

// Pins
const int pirPin = 27;
const int buzzerPin = 25;

const int redPin = 16;
const int greenPin = 17;
const int bluePin = 18;

const int servoPin = 4;

// Servo positions
const int servoCenter = 90;
const int servoRight = 105;
const int servoLeft = 75;

// Timing
unsigned long lastMotionTime = 0;
const unsigned long cooldown = 5000; // 5 seconds before triggering again

void setup() {
  Serial.begin(115200);
  delay(1000);

  pinMode(pirPin, INPUT);
  pinMode(buzzerPin, OUTPUT);

  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  digitalWrite(buzzerPin, LOW);
  setRGB(0, 0, 0);

  // Servo setup
  lightningServo.attach(servoPin);
  lightningServo.write(servoCenter);
  delay(500);

  Wire.begin(21, 22);
  lcd.init();
  lcd.backlight();

  showIdleMessage();

  Serial.println("System ready");
}

void loop() {
  int motionDetected = digitalRead(pirPin);

  if (motionDetected == HIGH && millis() - lastMotionTime > cooldown) {
    lastMotionTime = millis();

    Serial.println("Motion detected!");

    showMotionMessage();

    // Friendly attention sequence
    wakeUpLightning();
    playFriendlyBeeps();
    blinkRGB();
    friendlyLightningMove();

    showIdleMessage();
  }
}

void showMotionMessage() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Hello there!");
  lcd.setCursor(0, 1);
  lcd.print("Welcome to the");
  lcd.setCursor(0, 2);
  lcd.print("Prototyping Lab");
  lcd.setCursor(0, 3);
  lcd.print("Please register :)");
}

void showIdleMessage() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Welcome!");
  lcd.setCursor(0, 1);
  lcd.print("Approach to start");
  lcd.setCursor(0, 2);
  lcd.print("Please register");
  lcd.setCursor(0, 3);
  lcd.print("your visit :)");

  setRGB(0, 0, 1); // Blue idle light
  lightningServo.write(servoCenter);
}

void playFriendlyBeeps() {
  digitalWrite(buzzerPin, HIGH);
  delay(120);
  digitalWrite(buzzerPin, LOW);
  delay(80);

  digitalWrite(buzzerPin, HIGH);
  delay(120);
  digitalWrite(buzzerPin, LOW);
  delay(80);

  digitalWrite(buzzerPin, HIGH);
  delay(220);
  digitalWrite(buzzerPin, LOW);
}

void blinkRGB() {
  for (int i = 0; i < 3; i++) {
    setRGB(0, 1, 1); // Cyan
    delay(250);

    setRGB(0, 0, 0);
    delay(250);
  }
}

void wakeUpLightning() {
  // Small initial movement, like the lightning is waking up
  lightningServo.write(servoCenter);
  delay(150);

  lightningServo.write(servoRight);
  delay(250);

  lightningServo.write(servoCenter);
  delay(150);
}

void friendlyLightningMove() {
  // Friendly wiggle movement
  lightningServo.write(servoRight);
  delay(250);

  lightningServo.write(servoLeft);
  delay(250);

  lightningServo.write(servoRight);
  delay(200);

  lightningServo.write(servoCenter);
  delay(250);
}

void registrationSuccessMove() {
  // Optional movement for later, when you add NFC or button registration
  lightningServo.write(servoRight);
  delay(150);

  lightningServo.write(servoLeft);
  delay(150);

  lightningServo.write(servoRight);
  delay(150);

  lightningServo.write(servoCenter);
  delay(200);
}

void setRGB(int red, int green, int blue) {
  // Common cathode RGB LED:
  // HIGH turns color ON, LOW turns it OFF
  digitalWrite(redPin, red ? HIGH : LOW);
  digitalWrite(greenPin, green ? HIGH : LOW);
  digitalWrite(bluePin, blue ? HIGH : LOW);
}