#include "BLEDevice.h"

void setup() {
  Serial.begin(115200);
  BLEDevice::init(""); // Initialize BLE device

  BLEScan* pBLEScan = BLEDevice::getScan(); // Create new scan
  pBLEScan->setActiveScan(true); // Active scan uses more power, but get results faster
  BLEScanResults foundDevices = pBLEScan->start(30); // Scan for 30 seconds

  Serial.println("Scanning completed");
  Serial.println("Devices found: " + String(foundDevices.getCount()));

  for (int i = 0; i < foundDevices.getCount(); i++) {
    BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i);
    Serial.println("\nFound Device: " + String(advertisedDevice.toString().c_str()));

    // Now connect to the device and then discover its services and characteristics
    BLEClient* pClient = BLEDevice::createClient();
    Serial.println("Connecting to: " + String(advertisedDevice.getAddress().toString().c_str()));

    if (pClient->connect(&advertisedDevice)) {
      Serial.println("Connected to device!");
      // Obtain references to all services
      std::map<std::string, BLERemoteService*>* pRemoteServices = pClient->getServices();
      for (auto &myService : *pRemoteServices) {
        Serial.println("Service: " + String(myService.first.c_str()));
        BLERemoteService* pRemoteService = myService.second;

        // List all characteristics of this service
        std::map<std::string, BLERemoteCharacteristic*>* pChars = pRemoteService->getCharacteristics();
        for (auto &myChar : *pChars) {
          String properties = getCharacteristicProperties(myChar.second);
          Serial.print("\tCharacteristic: " + String(myChar.first.c_str()) + " | Properties: " + properties);

          // Read descriptors of the characteristic
          std::map<std::string, BLERemoteDescriptor*>* pDescs = myChar.second->getDescriptors();
          for (auto &desc : *pDescs) {
            std::string descValue = desc.second->readValue();
            Serial.print(" | Descriptor: " + String(desc.first.c_str()) + " Value: " + String(descValue.c_str()));
          }

          Serial.println();
        }
      }
      pClient->disconnect();
    } else {
      Serial.println("Failed to connect.");
    }
  }
}

String getCharacteristicProperties(BLERemoteCharacteristic* pChar) {
  String propDesc = "";
  if (pChar->canRead()) propDesc += "read ";
  if (pChar->canWrite()) propDesc += "write ";
  if (pChar->canWriteNoResponse()) propDesc += "write_no_resp ";
  if (pChar->canNotify()) propDesc += "notify ";
  if (pChar->canIndicate()) propDesc += "indicate ";
  propDesc.trim();
  return propDesc;
}

void loop() {
  // Nothing to do here
}
