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

#define ROW_NUM 4
#define ROW_COL 4
#define LED_RED_PIN 15
#define LED_GREEN_PIN 2
#define SERVO_SIG 23
#define SERVO_RELAY 1

char keys[ROW_NUM][ROW_COL] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

char password[4] = {'1', '2', '3', '4'};

int isLoggedIn = 0;

byte PIN_COL[ROW_NUM] = {26, 25, 33, 32};
byte PIN_ROWS[ROW_COL] = {13, 12, 14, 27};

LiquidCrystal_I2C lcd(0x27, 16, 2);
Keypad keypad = Keypad(makeKeymap(keys), PIN_ROWS, PIN_COL, ROW_NUM, ROW_COL);
Servo myservo;

void clearDisplay() {
  lcd.setCursor(0, 0);
  for(int i = 0; i < 16 * 2; i++) {
    lcd.print(" ");
  }
  lcd.setCursor(0, 0);
}

void displayMessage(char *msg) {
  clearDisplay();
  lcd.print(msg);
}


void initDisplay() {

  lcd.init();
  lcd.backlight();
  displayMessage("Setup OK");
  delay(100);
  clearDisplay();

}



void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Serial OK");

  pinMode(LED_RED_PIN, OUTPUT);
  pinMode(LED_GREEN_PIN, OUTPUT);
  pinMode(SERVO_RELAY, OUTPUT);

  digitalWrite(LED_RED_PIN, LOW);
  digitalWrite(LED_GREEN_PIN, LOW);
  digitalWrite(SERVO_RELAY, LOW);

  initDisplay();

  myservo.attach(SERVO_SIG);

}

int checkPassword(char PIN[]) {
  for(int i = 0; i < 4; i++) {
    if(PIN[i] != password[i]) {

      return -1;
    }
  }
  return 0;
}


void tryLogin() {

  char PIN[4] = {'1', '2', '3', '4'};
  int column = 0;
  displayMessage("Enter LOGIN: ");
  lcd.setCursor(column, 1);

  for(int i = 0; i < 4; i++) {
    
    while(1) {
      char key = keypad.getKey();
      if(key) {
        PIN[i]= key;
        break;
      }
    }


    lcd.print(PIN[i]);


  }

  if(checkPassword(PIN) < 0) {
    displayMessage("Login error!");
    digitalWrite(LED_RED_PIN, HIGH);
    digitalWrite(LED_GREEN_PIN, LOW);
    delay(1000);
  }
  else {
    displayMessage("Login succesfull!");
    digitalWrite(LED_RED_PIN, LOW);
  digitalWrite(LED_GREEN_PIN, HIGH);
    delay(1000);
    isLoggedIn = 1;
  }
}


void loop() {
  // put your main code here, to run repeatedly:
  delay(100); // this speeds up the simulation
  
  digitalWrite(LED_RED_PIN, LOW);
  digitalWrite(LED_GREEN_PIN, LOW);

  if(isLoggedIn == 0) {
    tryLogin();
  }

  else {
    digitalWrite(SERVO_RELAY, HIGH);
    myservo.write(180);
    delay(1000);
    myservo.write(0);
    delay(1000);
    digitalWrite(SERVO_RELAY, LOW);
    delay(1000);
  }

  clearDisplay();
}