#include <ESP32Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Password.h>

#define servoPin 15

Servo servo;

LiquidCrystal_I2C lcd(0x27, 16, 2);

const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'c'},
  {'*', '0', '#', 'D'},
};
byte rowPins[ROWS] = {23, 19, 18, 5};
byte colPins[COLS] = {17, 16, 4, 2};

bool isDoorLocked = true;
Password password = Password("43971005");
//Password password = Password("1234");

byte maxPasswordLength = 8;
byte currentPasswordLength = 0;

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(115200);
  servo.attach(servoPin);
 servo.write(10);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Door LOCK System");
  delay(2000);
  lcd.clear();
}

void loop() {
  lcd.setCursor(3, 0);
  isDoorLocked ? lcd.print("DOOR LOCKED") : lcd.print("DOOR OPEN");

  char key = keypad.getKey();
  Serial.println(key);
  if (key != NO_KEY) {
    delay(100);

    if (key == '#') {
      resetPassword();
    } else if (key == '*') {
      isDoorLocked = !isDoorLocked;
      isDoorLocked ? doorLocked() : doorOpen();
    } else {
      processNumberKey(key);
    }
  }
}

void processNumberKey(char key) {
  if (currentPasswordLength < maxPasswordLength) {
    lcd.setCursor(currentPasswordLength + 5, 1);
    lcd.print("*");
    password.append(key);
    currentPasswordLength++;
  }
}

void doorLocked() {
  if (password.evaluate()) {
    servo.write(10);
    displayMessage("Password Correct", "LOCKED");
  } else {
    displayMessage("Wrong Password", "Try Again");
  }
  resetPassword();
}

void doorOpen() {
  if (password.evaluate()) {
    servo.write(180);
    displayMessage("Password Correct", "UNLOCKED");
  } else {
    displayMessage("Wrong Password", "Try Again");
  }
  resetPassword();
}

void resetPassword() {
  password.reset();
  currentPasswordLength = 0;
  lcd.clear();
  lcd.setCursor(0, 0);
}

void displayMessage(const char *line1, const char *line2) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(line1);
  lcd.setCursor(3, 1);
  lcd.print(line2);
  delay(3000);
  lcd.clear();
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
servo1:GND
servo1:V+
servo1:PWM
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4