#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Adafruit_NeoPixel.h>

// --- External LED pins ---
#define LED1 9
#define LED2 10
#define LED3 11

// --- Onboard NeoPixel RGB LED ---
#define NEOPIXEL_PIN 8
#define NUMPIXELS 1
Adafruit_NeoPixel pixels(NUMPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

// --- BLE Server Callbacks ---
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("Device connected!");
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("Device disconnected!");
    pServer->getAdvertising()->start(); // restart advertising
  }
};

// --- BLE Characteristic Callbacks ---
class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String value = pCharacteristic->getValue();
    if (value.length() == 0) return;

    Serial.print("Received: ");
    Serial.println(value);

    // --- External LEDs ---
    if      (value == "led1_on") digitalWrite(LED1, HIGH);
    else if (value == "led1_off") digitalWrite(LED1, LOW);
    else if (value == "led2_on") digitalWrite(LED2, HIGH);
    else if (value == "led2_off") digitalWrite(LED2, LOW);
    else if (value == "led3_on") digitalWrite(LED3, HIGH);
    else if (value == "led3_off") digitalWrite(LED3, LOW);

    // --- Onboard NeoPixel RGB LED ---
    else if (value == "rgb_off") pixels.setPixelColor(0, 0, 0, 0);
    else if (value == "rgb_red") pixels.setPixelColor(0, 255, 0, 0);
    else if (value == "rgb_green") pixels.setPixelColor(0, 0, 255, 0);
    else if (value == "rgb_blue") pixels.setPixelColor(0, 0, 0, 255);
    else if (value == "rgb_white") pixels.setPixelColor(0, 255, 255, 255);

    pixels.show();
  }
};

void setup() {
  Serial.begin(115200);
  delay(1000);

  // --- Setup external LEDs ---
  pinMode(LED1, OUTPUT); digitalWrite(LED1, LOW);
  pinMode(LED2, OUTPUT); digitalWrite(LED2, LOW);
  pinMode(LED3, OUTPUT); digitalWrite(LED3, LOW);

  // --- Setup onboard NeoPixel and turn off ---
  pixels.begin();
  pixels.setPixelColor(0, 0, 0, 0);
  pixels.show();

  // --- Setup BLE ---
  Serial.println("Starting BLE...");

  BLEDevice::init("ESP32-C3-BLE");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  BLEService *pService = pServer->createService(BLEUUID((uint16_t)0xFFE0));

  pCharacteristic = pService->createCharacteristic(
                      BLEUUID((uint16_t)0xFFE1),
                      BLECharacteristic::PROPERTY_READ |
                      BLECharacteristic::PROPERTY_WRITE |
                      BLECharacteristic::PROPERTY_NOTIFY
                    );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Hello from ESP32");

  pService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->start();

  Serial.println("BLE Ready! Waiting for connection...");
}

void loop() {
  // Nothing needed here; BLE events handled in callbacks
}