#include <Keypad.h>
#include <ESP32Servo.h>
#include <WiFi.h>
#include <PubSubClient.h>

const char *ssid = "Wokwi-GUEST";
const char *password = "";
const char *mqtt_server = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi()
{
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char *topic, byte *payload, unsigned int length)
{
  // Handle incoming MQTT messages if needed
}

void reconnect()
{
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str()))
    {
      Serial.println("Connected");
      client.publish("/ThinkIOT/Publish", "Welcome");
      client.subscribe("/ThinkIOT/Subscribe");
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

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

uint8_t colPins[COLS] = { 14, 27, 26, 25 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 33, 32, 13, 12 }; // Pins connected to R1, R2, R3, R4

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
Servo myservo;  // create servo object to control a servo

int inputPin = 34;
int alarmLed = 23;
int buzzer = 22;
bool stateDoor = false;


String safeNumber = "";
String message = "";
int flag = 0;
void setup() {
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  pinMode(alarmLed, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);      // declare LED as output
  myservo.attach(16);
  myservo.write(0);

  Serial.begin(115200);
  Serial.println("Please Enter A new Password");
  while (safeNumber.length() < 4) {
    char key = keypad.getKey();
    if (key != NO_KEY) {
      Serial.println(key);
      safeNumber += key;
    }
  }
  message = "A new Password= " + safeNumber;
  Serial.println(message);

}

void loop() {

  if (!client.connected())
  {
    reconnect();
  }
  client.loop();
  if (flag == 0) {
    client.publish("/ThinkIOT/tempValue", message.c_str());
    flag = 1;
  }
  char key = keypad.getKey();
  Serial.println(stateDoor);

  if (key == 'D') {
    Serial.println("Please Enter A  Password To Enter");
    checkPassword(safeNumber);
  }

  else if (key == 'C') {
    Serial.println("Please Enter A  Password To Exit");
    checkPassword(safeNumber);
    stateDoor = false;
  }


  int sensor = digitalRead(inputPin);
  Serial.println(stateDoor);

  if (sensor == HIGH && stateDoor == false) {
    alarm();
  }
  delay(10);
}

void alarm() {
  int highFrequency = 1200;
  int lowFrequency = 800;
  int duration = 200;
  client.publish("/ThinkIOT/tempValue", "Alarm!!!!!");

  for (int i = 0; i < 10; i++) {
    tone(buzzer, highFrequency, duration);
    digitalWrite(alarmLed, HIGH);
    delay(duration);
    tone(buzzer, lowFrequency, duration);
    digitalWrite(alarmLed, LOW);
    delay(duration);
  }
}

void checkPassword(String password) {
  String enteredPassword = "";
  while (enteredPassword.length() < 4) {
    char key = keypad.getKey();
    if (key != NO_KEY) {
      Serial.println(key);
      enteredPassword += key;
    }
  }

  if (enteredPassword == password) {
    Serial.println("Password Correct!");
    stateDoor = true;
    myservo.write(90);
    delay(2000);
    myservo.write(0);
  } else {
    client.publish("/ThinkIOT/tempValue", "some one try to enter invalid password!!");
    Serial.println("Password Incorrect!");
    myservo.write(0);
    alarm();
    stateDoor = false;
  }
}
$abcdeabcde151015202530fghijfghij