#include "BleServer.h"
#include "esp_log.h"
#include "BLE_SP110E.h"
#include "BLE_UpdateService.h"
#include "BleSettings.h"

static const char* tag = "BleServer";


// Class for handling server events
class ServerCallbacks : public NimBLEServerCallbacks {
    void onConnect(NimBLEServer* pServer) override {
        ESP_LOGI(tag, "Client connected");
        // Ensure advertising remains active even after a client connects
        NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
        if (pAdvertising != nullptr) {
            if (!pAdvertising->isAdvertising()) {
                pAdvertising->start();
            }
        }
    }

    void onDisconnect(NimBLEServer* pServer) override {
        ESP_LOGI(tag, "Client disconnected");
        // Restart advertising on disconnect to keep it active always
        NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
        if (pAdvertising != nullptr) {
            if (!pAdvertising->isAdvertising()) {
                pAdvertising->start();
            }
        }
    }
};

void Init_BleServer( bool isSP110EActive, bool isUpgradeActive) {

    ESP_LOGI(tag, "Initializing BLE...");
    static bool isInitialized = false;
    if (!isInitialized) {
        NimBLEDevice::init(BTDeviceName.c_str());
        //NimBLEDevice::setMTU(247); // Set preferred MTU size (max 247 for BLE) 
    isInitialized = true;
    }

    NimBLEServer *pServer = NimBLEDevice::createServer();
    if (pServer == nullptr) {
        ESP_LOGE(tag, "Failed to create BLE server");
        return;
    }

    // setup the Sever Callbacks
    pServer->setCallbacks(new ServerCallbacks());
      
    // Initialize BLE with SP110E Service
    if(isSP110EActive){
        Init_BLE_SP110E(pServer);
    }

    // Initialize BLE with Upgrade Service
    if(isUpgradeActive){
        Init_UpgradeBLEService(pServer);
    }

    // Start BLE advertising
    NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
    if (pAdvertising != nullptr) {
    if (!pAdvertising->isAdvertising() && !pAdvertising->start()) {
            ESP_LOGE(tag, "Failed to start advertising");
            return;
        }
    } else {
        ESP_LOGE(tag, "Failed to get advertising object");
    }
}