#define BLYNK_TEMPLATE_ID "TMPL6KJBMnG4K"
#define BLYNK_TEMPLATE_NAME "Smart Home Security System Final Project"
#define BLYNK_AUTH_TOKEN ""

#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiClientSecure.h>
#include <FastLED.h>

char ssid[] = ""; // Replace with your WiFi SSID
char pass[] = ""; // Replace with your WiFi Password

const int trigPin = 16;
const int echoPin = 17;
const int vibrationPin = 34;

const char* intrusionHost = "hook.eu2.make.com";
const char* knockHost = "hook.eu2.make.com";
const char* intrusionPath = "/zd4mcdj29t3mc3wjfo638o4m3rs6c9je";
const char* knockPath = "/lsgt4e9xh5mhned4meqwaswxur6qmrk4";
const int httpsPort = 443;

WiFiClientSecure wifiClient; // Declare WiFiClientSecure instance

#define LED_PIN 13
#define NUM_LEDS 12
CRGB leds[NUM_LEDS];

void sendWebhook(const char* host, const char* path);
void flashLEDs();

void setup() {
  Serial.begin(115200);
  
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); 

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(vibrationPin, INPUT);

  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
  FastLED.clear();
  FastLED.show();

  delay(2000); // Allow sensors to stabilize for 2 seconds

  // Read initial sensor values to clear any spurious readings
  long duration, distance;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) / 29.1;
  int vibration = analogRead(vibrationPin);

  // Print initial values for debugging
  Serial.print("Initial Distance: ");
  Serial.print(distance);
  Serial.println(" mm");
  Serial.print("Initial Vibration: ");
  Serial.println(vibration);

  Serial.println("Setup complete, starting loop...");
}

void loop() {
  long duration, distance;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) / 29.1;
  Blynk.virtualWrite(V1, distance); // Send distance data to Blynk
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" mm");

  // Trigger event if distance is less than a threshold (e.g., 20 cm)
  if (distance < 20) {
    Blynk.logEvent("intrusion_detected");
    Serial.println("Intrusion detected, distance below 20 cm");
    sendWebhook(intrusionHost, intrusionPath);
    flashLEDs(); // Flash LEDs for intrusion detection
  }

  int vibration = analogRead(vibrationPin);
  Blynk.virtualWrite(V2, vibration); // Send vibration data to Blynk
  Serial.print("Vibration: ");
  Serial.println(vibration);

  // Trigger event if vibration is detected (value above a threshold, e.g., 25)
  if (vibration > 25) {
    Blynk.logEvent("vibration_detected");
    Serial.println("Vibration alert, value above 25");
    sendWebhook(knockHost, knockPath);
  }

  Blynk.run();
}

void sendWebhook(const char* host, const char* path) {
  wifiClient.setInsecure(); // Use this only for testing purposes
  
  if (!wifiClient.connect(host, httpsPort)) {
    Serial.println("Connection failed!");
    return;
  }

  String url = String("GET ") + path + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "User-Agent: ESP32\r\n" + 
               "Connection: close\r\n\r\n";

  wifiClient.print(url);

  while (wifiClient.connected()) {
    String line = wifiClient.readStringUntil('\n');
    if (line == "\r") {
      break;
    }
  }

  while (wifiClient.available()) {
    String line = wifiClient.readStringUntil('\n');
    Serial.println(line);
  }

  wifiClient.stop();
}

void flashLEDs() {
  for (int i = 0; i < 10; i++) { // Flash for 10 seconds
    for (int j = 0; j < NUM_LEDS; j++) {
      leds[j] = CRGB::Red;
    }
    FastLED.show();
    delay(500);

    for (int j = 0; j < NUM_LEDS; j++) {
      leds[j] = CRGB::Blue;
    }
    FastLED.show();
    delay(500);
  }

  FastLED.clear();
  FastLED.show();
}