#ifndef BLUETOOTH_LE_UART_SERVER
#define BLUETOOTH_LE_UART_SERVER

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

class BluetoothLeUartServerCallbacks;

/*!
 * \brief The BluetoothLeUartServer class can be used to connect to another Bluetooth LE device (like an Android phone) effordlessly.
 * 
 * Example use
 * \code
 * #include <Arduino.h>
 * 
 * BluetoothLeUartServer* server;
 * 
 * class MyCallbacks : public BluetoothLeUartServerCallbacks
 * {
 *   virtual void onDeviceConnectedChanged(bool deviceConnected)
 *   {
 *     Serial.println("Device connected changed");
 *   };
 *   virtual void onDataReceived(String data)
 *   {
 *     Serial.println("Got some data: " + data);
 *   };
 * };
 * 
 * void setup()
 * {
 *     server = new BluetoothLeUartServer("LedDisplay1", "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e");
 *     server->setCallbacks(new MyCallbacks());
 * }
 *
 * void loop()
 * {
 *     if(server->getDeviceConnected())
 *         server->sendData("PING");
 *     delay(1000);
 * }
 * \endcode
 */
class BluetoothLeUartServer : protected BLEServerCallbacks, protected BLECharacteristicCallbacks
{

public:
    explicit BluetoothLeUartServer(String deviceName, const char uartServiceUUID[36], const char rxUUID[36], const char txUUID[36]);

    // befriend for callbacks
    friend class BLEServer;
    friend class BLECharacteristic;

    // public functions
    void setCallbacks(BluetoothLeUartServerCallbacks *callbacks);
    void sendData(String data);

    bool getDeviceConnected();
    bool disconnectCurrentDevice();

    String getDeviceAddress();

protected:
    // callbacks for BLEServer
    void onConnect(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) override;
    void onDisconnect(BLEServer *pServer) override;

    // callback for BLECharacteristic
    void onWrite(BLECharacteristic *rxCharacteristic) override;

private:
    // service and characteristic UUIDs
    const char *uartServiceUUID;
    const char *rxUUID;
    const char *txUUID;


	esp_gatt_perm_t permissions;

    // BLE Objects
    BLEServer *bleServer;
    BLEService *bleService;
    BLECharacteristic *txCharacteristic;
    BLECharacteristic *rxCharacteristic;

    // helpers
    bool deviceConnected;
    uint16_t deviceConnectionId;
    BluetoothLeUartServerCallbacks *callbacks;
};

class BluetoothLeUartServerCallbacks
{
public:
    virtual void onDeviceConnectedChanged(bool deviceConnected);
    virtual void onDataReceived(String data);
};

#endif // BLUETOOTH_LE_UART_SERVER