#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <ESP32Servo.h>
#include "icons.h"
#include <Wire.h>
#include "WiFi.h"

#include "ThingsBoard.h"
#include "DHTesp.h"

/* Locking mechanism definitions */
#define SERVO_PIN 23
#define SERVO_LOCK_POS   20
#define SERVO_UNLOCK_POS 90

Servo ServoMotor; // menamakan objek servo

#define ledmerah 33
#define ledungu 25
#define ledbirumuda 26
#define ledputih1 27 //lampu dalam
#define ledputih2 14 // lampu luar kandang


#define TX2 6  //re-mapping pin
#define RX2 7  //re-mapping pin

#define TX0 13 //re-mapping pin
#define RX0 12  //re-mapping pin
// re-mapping ternyata tidak bisa di wokwi

int buzzpin = 32;
int pinPIR = 13;
int gerakPir;
int position = 0;
char* password = "789"; 

LiquidCrystal_I2C lcd(0x27, 20, 4);

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] = { 5, 4, 2, 15 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 33, 25, 19, 18 }; // Pins connected to R1, R2, R3, R4

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

/* SafeState stores the secret code in EEPROM */
SafeState safeState;

#define WIFI_SSID           "Wokwi-GUEST" //deklarasi ssid wifi yang digunakan, disesuiakan dengan wifi yang digunakan
#define WIFI_PASSWORD       "" //deklarasi password wifi yang digunakan

// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
#define TOKEN               "RHhzutVyzHttBvgdDKEu" //SESUAIKAN token masing-masing
#define THINGSBOARD_SERVER  "thingsboard.cloud" //alamat server dari thingsboard, jika menggunakan server probadi alamatnya bisa disesuaikan, apabila menggunakan server yang disediakan thingsboard alamatnya adalah thingsboar.cloud

const int DHT1_PIN = 35; //deklarasi nomor pin dht
const int DHT2_PIN = 34; //deklarasi nomor pin dht

DHTesp dhtSuhu; // suhu dan kelembaban
DHTesp dhtGas; // gas amonia dan metana

// Deklarasi Thingsboard client dan mengubah perintah WiFiClient menjadi espClient
WiFiClient espClient; 
// Deklarasi untuk mengubah perintah Thingsboard menjadi tb dan memasukkan perintah WiFiClient yang sudah diubah menjadi espClient ke dalam library Thingsboard
ThingsBoard tb(espClient);

int status = WL_IDLE_STATUS; //deklarasi status wifi yang dimasukkan dalam variabel status

void connect() //void mengoneksikan esp dengan wifi pertama kali
{
  Serial.println("Connecting to AP ...");
  // attempt to connect to WiFi network

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {

    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected to AP");
}

void reconnect() { //peintah recconect wifi apabila esp terputus dengan jaringan wifinya
  // Loop until we're reconnected
  status = WiFi.status();
  if ( status != WL_CONNECTED) {
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("Connected to AP");
  }
}
/*
void lock() {
  lockServo.write(SERVO_LOCK_POS);
  safeState.lock();
}

void unlock() {
  lockServo.write(SERVO_UNLOCK_POS);
}

void showStartupMessage() {
  lcd.setCursor(4, 0);
  lcd.print("Welcome!");
  delay(500);
  lcd.setCursor(0,1);
  lcd.println("IoT2-12 Kelompok 1");
  lcd.setCursor(0, 2);
  String message = "Farm Controller";
  for (byte i = 0; i < message.length(); i++) {
    lcd.print(message[i]);
    delay(50);
  }
  delay(500);
}

String inputSecretCode() {
  lcd.setCursor(5, 1);
  lcd.print("[____]");
  lcd.setCursor(6, 1);
  String result = "";
  while (result.length() < 4) {
    char key = keypad.getKey();
    if (key >= '0' && key <= '9') {
      lcd.print('*');
      result += key;
    }
  }
  Serial.println(result);
  return result;
}

void showWaitScreen(int delayMillis) {
  lcd.setCursor(2, 1);
  lcd.print("[..........]");
  lcd.setCursor(3, 1);
  for (byte i = 0; i < 10; i++) {
    delay(delayMillis);
    lcd.print("=");
  }
}

bool setNewCode() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Enter new code:");
  String newCode = inputSecretCode();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Confirm new code");
  String confirmCode = inputSecretCode();

  if (newCode.equals(confirmCode)) {
    safeState.setCode(newCode);
    return true;
  } else {
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Code mismatch");
    lcd.setCursor(0, 1);
    lcd.print("Safe not locked!");
    delay(2000);
    return false;
  }
}

void showUnlockMessage() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write(ICON_UNLOCKED_CHAR);
  lcd.setCursor(4, 0);
  lcd.print("Unlocked!");
  lcd.setCursor(15, 0);
  lcd.write(ICON_UNLOCKED_CHAR);
  delay(1000);
}

void safeUnlockedLogic() {
  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.write(ICON_UNLOCKED_CHAR);
  lcd.setCursor(2, 0);
  lcd.print(" # to lock");
  lcd.setCursor(15, 0);
  lcd.write(ICON_UNLOCKED_CHAR);

  bool newCodeNeeded = true;

  if (safeState.hasCode()) {
    lcd.setCursor(0, 1);
    lcd.print("  A = new code");
    newCodeNeeded = false;
  }

  auto key = keypad.getKey();
  while (key != 'A' && key != '#') {
    key = keypad.getKey();
  }

  bool readyToLock = true;
  if (key == 'A' || newCodeNeeded) {
    readyToLock = setNewCode();
  }

  if (readyToLock) {
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.write(ICON_UNLOCKED_CHAR);
    lcd.print(" ");
    lcd.write(ICON_RIGHT_ARROW);
    lcd.print(" ");
    lcd.write(ICON_LOCKED_CHAR);

    safeState.lock();
    lock();
    showWaitScreen(100);
  }
}

void safeLockedLogic() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write(ICON_LOCKED_CHAR);
  lcd.print(" Safe Locked! ");
  lcd.write(ICON_LOCKED_CHAR);

  String userCode = inputSecretCode();
  bool unlockedSuccessfully = safeState.unlock(userCode);
  showWaitScreen(200);
Serial.print(userCode); // nanti dihapus
  if (unlockedSuccessfully) {
    showUnlockMessage();
    unlock();
  } else {

tone(buzzpin,250,250);    // nanti dihapus
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Access Denied!");
    showWaitScreen(100);
  }
}
*/

void setup() {
  // Setup LCD with backlight and initialize
  lcd.init();
  lcd.backlight();

  Serial.begin(9600);
   // Set lockOutput as an OUTPUT pin

  pinMode(SERVO_PIN, OUTPUT);
  pinMode(buzzpin, OUTPUT);
//  pinMode(pinPIR, INPUT);

//  Serial.begin(115200);
 
  Serial.println("Hello, ESP32!"); // nanti dihapus

  init_icons(lcd);

  ServoMotor.attach(SERVO_PIN);
LockedPosition(true);
  /* Make sure the physical lock is sync with the EEPROM state */
//  Serial.begin(115200);
 // if (safeState.locked()) {
 //   lock();
//  } else {
 //   unlock();
 // }

//  showStartupMessage();  
}

void loop() {
//  tone(buzzpin,250,250);
char key = keypad.getKey();
if (key == '*' || key == '#')
{
position = 0;
LockedPosition(true);
}
if (key == password[position])
{
position ++;
}
if (position == 3)
{
LockedPosition(false);
}
delay(100);
}

void LockedPosition(int locked)
{
if (locked)
{
//digitalWrite(RedpinLock, HIGH);
//digitalWrite(GreenpinUnlock, LOW);
ServoMotor.write(11);
}
else
{
//digitalWrite(RedpinLock, LOW);
//digitalWrite(GreenpinUnlock, HIGH);
ServoMotor.write(90);
}
Serial.println("been out");
}



void cekLampuLuar() {

}

void cekLampuKandang() {

}

void cekSuhuKelembaban() {

}

void cekAmoniaMetana() {

}


int cekPenyusup() {

  digitalWrite(pinPIR, LOW);
Serial.print("masuk penyusup");
  if(gerakPir==HIGH){  
    tone(buzzpin,500,250);
    lcd.clear();
    lcd.setCursor(0,4);
  Serial.print("di penyusup");    
    lcd.println("Ada penyusup");
    delay(500);
    lcd.clear();
    } else {
        digitalWrite(pinPIR, LOW);
        return gerakPir;
    }
    return gerakPir;
  }