// Working

#define SectorNumber "sector1"
const int threshold = 100;

#include <WiFi.h>
#include <FirebaseESP32.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);


int slot1cords = 16;
int slot2cords = 17;
int slot3cords = 18;

// status path
String slot1statuspath = "kailparking/" + String(SectorNumber) + "/slot1/status"; // path : "kailparking/sector1/slot1"
String slot2statuspath = "kailparking/" + String(SectorNumber) + "/slot2/status"; // path : "kailparking/sector1/slot1"
String slot3statuspath = "kailparking/" + String(SectorNumber) + "/slot3/status"; // path : "kailparking/sector1/slot1"

// cods path
String slot1cordspath = "kailparking/" + String(SectorNumber) + "/slot1/cords"; // path : "kailparking/sector1/slot1"
String slot2cordspath = "kailparking/" + String(SectorNumber) + "/slot2/cords"; // path : "kailparking/sector1/slot1"
String slot3cordspath = "kailparking/" + String(SectorNumber) + "/slot3/cords"; // path : "kailparking/sector1/slot1"

// fault path
String slot1faultpath = "kailparking/" + String(SectorNumber) + "/slot1/fault"; // path : "kailparking/sector1/slot1"
String slot2faultpath = "kailparking/" + String(SectorNumber) + "/slot2/fault"; // path : "kailparking/sector1/slot1"
String slot3faultpath = "kailparking/" + String(SectorNumber) + "/slot3/fault"; // path : "kailparking/sector1/slot1"

/*
paths:
kailparking/sector1/slot1
kailparking/sector1/slot2
kailparking/sector1/slot3
*/

//Provide the token generation process info.
#include <addons/TokenHelper.h>

//Provide the RTDB payload printing info and other helper functions.
#include <addons/RTDBHelper.h>

/* 1. Define the WiFi credentials */
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""

//For the following credentials, see examples/Authentications/SignInAsUser/EmailPassword/EmailPassword.ino

/* 2. Define the API Key */
#define API_KEY "AIzaSyDNkmRRBcDPfWCUNYdoaOQ08hyhmfQDzKM"

/* 3. Define the RTDB URL */
#define DATABASE_URL "https://smart-parking-system-5ed8b-default-rtdb.firebaseio.com/" 
//<databaseName>.firebaseio.com or <databaseName>.<region>.firebasedatabase.app

//Define Firebase Data object
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;

// Variable Decleration
int a,b, x, y;
int mycount = 123;

int slot1avar = 0;
int slot1bvar = 0;

int slot2avar = 0;
int slot2bvar = 0;

int slot3avar = 0;
int slot3bvar = 0;

// main slot var
int slot1var = 0;
int slot2var = 0;
int slot3var = 0;


//save requests
int prevslot1var = 0;
int prevslot2var = 0;
int prevslot3var = 0;

// Ultrasonic Pin Declare Part
const int trigPin1a = 23;
const int echoPin1a = 19;

const int trigPin1b = 5;
const int echoPin1b = 18;

const int trigPin2a = 4;
const int echoPin2a = 2;

const int trigPin2b = 13;
const int echoPin2b = 14;

const int trigPin3a = 27;
const int echoPin3a = 26;

const int trigPin3b = 25;
const int echoPin3b = 33;


//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701


//Fault Detection
int slot1Faultvar = 0;
int slot2Faultvar = 0;
int slot3Faultvar = 0;

int PrevSlot1Faultvar = 0;
int PrevSlot2Faultvar = 0;
int PrevSlot3Faultvar = 0;


int ReadUltra(int trigPin, int echoPin, int threshold){
  long duration;
  float distanceCm;

  // Clears the trigPin
  digitalWrite(trigPin, LOW);delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;
  
  // Convert to inches
  // distanceInch = distanceCm * CM_TO_INCH;
  
  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");Serial.println(distanceCm);
  // Serial.print("Distance (inch): ");
  // Serial.println(distanceInch);
  delay(1000);
  
  if ( distanceCm <= threshold){return 1;}
  else{return 0;}
}

void LcdStatus(int slo1,int slo2,int slo3){

  if (slo1 == 1){lcd.setCursor(3, 1);  lcd.print("F");}
  else{lcd.setCursor(3, 1);  lcd.print("E");}

  if (slo2 == 1){lcd.setCursor(8, 1);  lcd.print("F");}
  else{lcd.setCursor(8, 1);  lcd.print("E");}

  if (slo3 == 1){lcd.setCursor(13, 1);  lcd.print("F");}
  else{lcd.setCursor(13, 1);  lcd.print("E");}

}

void updateCords(){
  if (Firebase.setInt(fbdo, slot1cordspath, slot1cords)){Serial.println("Slot1 cords uploaded " + String(slot1cords));}
  else{Serial.println("Error Slot1 cords uploading");}delay(200);

  if (Firebase.setInt(fbdo, slot2cordspath, slot2cords)){Serial.println("Slot2 cords uploaded " + String(slot2cords));}
  else{Serial.println("Error Slot2 cords uploading");}delay(200);

  if (Firebase.setInt(fbdo, slot3cordspath, slot3cords)){Serial.println("Slot3 cords uploaded " + String(slot3cords));}
  else{Serial.println("Error Slot3 cords uploading");}delay(200);
  
}

int ultraCheck(int ultraA, int ultraB){
  if (ultraA == ultraB){return 0;}
  else{return 1;}
}


void ifFaultGenNotification(int slotNum, int slotNumVal){
  if (slotNum == 1){
    if (Firebase.setInt(fbdo, slot1faultpath, slotNumVal)){Serial.println("Slot1 fault uploaded " + String(slotNumVal));}
    else{Serial.println("Error Slot1 fault uploading");}delay(200);
  }

  if (slotNum == 2){
    if (Firebase.setInt(fbdo, slot2faultpath, slotNumVal)){Serial.println("Slot2 fault uploaded " + String(slotNumVal));}
    else{Serial.println("Error Slot2 fault uploading");}delay(200);
  }

  if (slotNum == 3){
    if (Firebase.setInt(fbdo, slot3faultpath, slotNumVal)){Serial.println("Slot3 fault uploaded " + String(slotNumVal));}
    else{Serial.println("Error Slot3 fault uploading");}delay(200);
  }
}



void setup()
{
  Serial.begin(115200);delay(2000);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");

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

  Serial.println();Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());Serial.println();

  Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION);

  /* Assign the api key (required) */
  config.api_key = API_KEY;
  config.database_url = DATABASE_URL;
  Firebase.begin(DATABASE_URL, API_KEY);

 // Firebase.reconnectWiFi(true);

  Firebase.setDoubleDigits(5);

  pinMode(trigPin1a, OUTPUT);
  pinMode(echoPin1a, INPUT);

  pinMode(trigPin1b, OUTPUT);
  pinMode(echoPin1b, INPUT);

  pinMode(trigPin2a, OUTPUT);
  pinMode(echoPin2a, INPUT);

  pinMode(trigPin2b, OUTPUT);
  pinMode(echoPin2b, INPUT);

  pinMode(trigPin3a, OUTPUT);
  pinMode(echoPin3a, INPUT);

  pinMode(trigPin3b, OUTPUT);
  pinMode(echoPin3b, INPUT);

  lcd.init();  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Kali_hackers");
  lcd.setCursor(0, 1);
  lcd.print("Smart Parking System");
  delay(1000);
  lcd.clear();
  lcd.setCursor(2, 0);  lcd.print("S1");
  lcd.setCursor(7, 0);  lcd.print("S2");
  lcd.setCursor(12, 0);  lcd.print("S3");
  updateCords();

// set all faults as '0"
Firebase.setInt(fbdo, slot1faultpath, 0);
Firebase.setInt(fbdo, slot2faultpath, 0);
Firebase.setInt(fbdo, slot3faultpath, 0);

}

void loop(){
  // Read Ultrasonics
  slot1avar = ReadUltra(trigPin1a, echoPin1a, threshold);delay(100);
  slot1bvar = ReadUltra(trigPin1b, echoPin1b, threshold);delay(100);

  slot2avar = ReadUltra(trigPin2a, echoPin2a, threshold);delay(100);
  slot2bvar = ReadUltra(trigPin2b, echoPin2b, threshold);delay(100);

  slot3avar = ReadUltra(trigPin3a, echoPin3a, threshold);delay(100);
  slot3bvar = ReadUltra(trigPin3b, echoPin3b, threshold);delay(100);


  // Ultra check
  slot1Faultvar = ultraCheck(slot1avar, slot1bvar);
  slot2Faultvar = ultraCheck(slot2avar, slot2bvar);
  slot3Faultvar = ultraCheck(slot3avar, slot3bvar);

  // update main slot var
  if (slot1Faultvar == 0){slot1var = slot1avar;}
  if (slot2Faultvar == 0){slot2var = slot2avar;}
  if (slot3Faultvar == 0){slot3var = slot3avar;}

  // display all slot status on LCD Screen
  LcdStatus(slot1var,slot2var,slot3var);


  if (Firebase.ready()){
    delay(200);

    if (prevslot1var == slot1var){Serial.println("Slot 1    same");}
    if (prevslot2var == slot2var){Serial.println("Slot 2    same");}
    if (prevslot3var == slot3var){Serial.println("Slot 3    same");}

      // Slot1 - data uploading
    if (slot1Faultvar == 0){
      if (prevslot1var != slot1var){
        if (Firebase.setInt(fbdo, slot1statuspath, slot1var)){Serial.println("Slot1 Data uploaded " + String(slot1var));}
        else{Serial.println("Error Slot1 data uploaded");}
        delay(200);
        if (PrevSlot1Faultvar != slot1Faultvar){prevslot1var = slot1var;ifFaultGenNotification(1, slot1Faultvar);PrevSlot1Faultvar=slot1Faultvar;}
      }
    }
    if (PrevSlot1Faultvar != slot1Faultvar){prevslot1var = slot1var;ifFaultGenNotification(1, slot1Faultvar);PrevSlot1Faultvar=slot1Faultvar;}

      // Slot2 - data uploading
    if (slot2Faultvar == 0){
      if (prevslot2var != slot2var){
        if (Firebase.setInt(fbdo, slot2statuspath, slot2var)){Serial.println("Slot2 Data uploaded " + String(slot2var));}
        else{Serial.println("Error Slot2 data uploaded");}
        delay(200);
        if (PrevSlot2Faultvar != slot2Faultvar){prevslot2var = slot2var;ifFaultGenNotification(2, slot2Faultvar);PrevSlot2Faultvar=slot2Faultvar;}
      }
    }
    if (PrevSlot2Faultvar != slot2Faultvar){prevslot2var = slot2var;ifFaultGenNotification(2, slot2Faultvar);PrevSlot2Faultvar=slot2Faultvar;}


      // Slot3 - data uploading
    if (slot3Faultvar == 0){
      if (prevslot3var != slot3var){
        if (Firebase.setInt(fbdo, slot3statuspath, slot3var)){Serial.println("Slot3 Data uploaded " + String(slot3var));}
        else{Serial.println("Error Slot3 data uploaded");}
        delay(200);
        if (PrevSlot3Faultvar != slot3Faultvar){prevslot3var = slot3var;ifFaultGenNotification(3, slot3Faultvar);PrevSlot3Faultvar=slot3Faultvar;}
      }
    }
      if (PrevSlot3Faultvar != slot3Faultvar){prevslot3var = slot3var;ifFaultGenNotification(3, slot3Faultvar);PrevSlot3Faultvar=slot3Faultvar;}

    Serial.println();Serial.println("------------------------------------");Serial.println();
    delay(10000);
  }
}