/** @file
 *
 * @defgroup ble_dfu Buttonless DFU Service Client
 * @{
 * @ingroup ble_sdk_srv
 * @brief Buttonless DFU Service module.
 *
 * @details This module implements a proprietary Buttonless Secure DFU Service Client. Only start Bootloader from friendly node for Smartphone
 *
 */

#ifndef BLE_DFU_C_H__
#define BLE_DFU_C_H__

#include "ble_db_discovery.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#include <stdint.h>


#ifdef __cplusplus
extern "C"
{
#endif

/**@brief   Macro for defining a ble_dfu_c instance.
 *
 * @param   _name   Name of the instance.
 * @hideinitializer
 */
#define BLE_DFU_C_DEF(_name)                                                                                                                                                                           \
    static ble_dfu_c_t _name;                                                                                                                                                                          \
    NRF_SDH_BLE_OBSERVER(_name##_obs, BLE_DFU_C_BLE_OBSERVER_PRIO, ble_dfu_c_on_ble_evt, &_name)

/** @brief Macro for defining multiple ble_dfu_c instances.
 *
 * @param   _name   Name of the array of instances.
 * @param   _cnt    Number of instances to define.
 * @hideinitializer
 */
#define BLE_DFU_C_ARRAY_DEF(_name, _cnt)                                                                                                                                                               \
    static ble_dfu_c_t _name[_cnt];                                                                                                                                                                    \
    NRF_SDH_BLE_OBSERVERS(_name##_obs, BLE_DFU_C_BLE_OBSERVER_PRIO, ble_dfu_c_on_ble_evt, &_name, _cnt)


/**@brief   SoC observer priority.
 * @details Priority of this module's SoC event handler.
 */
#define BLE_DFU_SOC_OBSERVER_PRIO 1

#define BLE_DFU_C_CHAR_UUID (0x0003)        /**< Value combined with vendor-specific base to create Unbonded Buttonless characteristic UUID. */
#define BLE_DFU_C_BONDED_CHAR_UUID (0x0004) /**< Value combined with vendor-specific base to create Bonded Buttonless characteristic UUID. */


/**@brief Nordic vendor-specific base UUID.
 */
#define BLE_NORDIC_VENDOR_BASE_UUID                                                                                                                                                                    \
    {                                                                                                                                                                                                  \
        {                                                                                                                                                                                              \
            0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, 0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E                                                                                             \
        }                                                                                                                                                                                              \
    }


    /**@brief Nordic DFU Client Service event type .
     */
    typedef enum
    {
        BLE_DFU_C_EVT_DISCOVERY_COMPLETE,  /**< Event indicating that the DFU Service and its characterisitcs was found.*/
        BLE_DFU_C_EVT_BOOTLOADER_STARTING, /**< Event indicating that the Bootloader will be started.*/
        BLE_DFU_C_EVT_DISCONNECTED,        /**< Event indicating that the DFU Server has disconnected.*/
    } ble_dfu_c_evt_type_t;

    typedef struct
    {
        uint16_t chr;
        uint16_t cccd;
    } ble_dfu_c_handles_t;

    /**@brief Structure containing the NUS event data received from the peer. */
    typedef struct
    {
        ble_dfu_c_evt_type_t evt_type;
        uint16_t conn_handle;
        uint16_t max_data_len;
        uint8_t * p_data;
        uint8_t data_len;
        ble_dfu_c_handles_t
            handles; /**< Handles on which the Nordic Uart service characteristics was discovered on the peer device. This will be filled if the evt_type is @ref BLE_NUS_C_EVT_DISCOVERY_COMPLETE.*/
    } ble_dfu_c_evt_t;

    // Forward declaration of the ble_nus_t type.
    typedef struct ble_dfu_c_s ble_dfu_c_t;

    /**@brief Nordic Buttonless DFU Service event handler type.
     */
    typedef void (*ble_dfu_c_evt_handler_t)(ble_dfu_c_t * p_ble_dfu_c, ble_dfu_c_evt_t const * p_evt);
    /**@brief Enumeration of Bootloader DFU response codes.
     */
    typedef enum
    {
        DFU_RSP_INVALID = 0x00,               /**< Invalid op code. */
        DFU_RSP_SUCCESS = 0x01,               /**< Success. */
        DFU_RSP_OP_CODE_NOT_SUPPORTED = 0x02, /**< Op code not supported. */
        DFU_RSP_OPERATION_FAILED = 0x04,      /**< Operation failed. */
        DFU_RSP_ADV_NAME_INVALID = 0x05,      /**< Requested advertisement name is too short or too long. */
        DFU_RSP_BUSY = 0x06,                  /**< Ongoing async operation. */
        DFU_RSP_NOT_BONDED = 0x07,            /**< Buttonless unavailable due to device not bonded. */
    } ble_dfu_c_rsp_code_t;


    /**@brief Enumeration of Bootloader DFU Operation codes.
     */
    typedef enum
    {
        DFU_OP_RESERVED = 0x00,         /**< Reserved for future use. */
        DFU_OP_ENTER_BOOTLOADER = 0x01, /**< Enter bootloader. */
        DFU_OP_SET_ADV_NAME = 0x02,     /**< Set advertisement name to use in DFU mode. */
        DFU_OP_RESPONSE_CODE = 0x20     /**< Response code. */
    } ble_dfu_c_op_code_t;


    /**@brief DFU Client structure. */
    struct ble_dfu_c_s
    {
        uint8_t uuid_type;    /**< UUID type for DFU UUID. */
        uint16_t conn_handle; /**< Connection handle for the current peer. */
        ble_dfu_c_handles_t handles;
	bool indication_enabled;
        ble_dfu_c_evt_handler_t evt_handler; /**< Event handler that is called upon Buttonless DFU events. See @ref ble_dfu_buttonless_evt_type_t. */
    };


    /**@brief Type used to initialize the Secure DFU Buttonless Service.
     */
    typedef struct
    {
        ble_dfu_c_evt_handler_t evt_handler; /**< Bootloader event handler. */
    } ble_dfu_c_init_t;


    /**@brief Function for initializing the Device Firmware Update module.
     *
     * @param[in]   p_ble_dfu_c  Pointer to the DFU client structure.
     * @param[in]   p_dfu_init   Structure containing the values of characteristics needed by the
     *                           service.
     * @retval      NRF_SUCCESS on successful initialization of the service.
     */
    uint32_t ble_dfu_c_init(ble_dfu_c_t * p_ble_dfu_c, const ble_dfu_c_init_t * p_ble_dfu_c_init);


    /**@brief Function for handling events from the database discovery module.
     *
     * @details This function will handle an event from the database discovery module, and determine
     *          if it relates to the discovery of DFU at the peer. If so, it will
     *          call the application's event handler indicating that DFU has been
     *          discovered at the peer. It also populates the event with the service related
     *          information before providing it to the application.
     *
     * @param[in] p_ble_dfu_c Pointer to the DFU client structure.
     * @param[in] p_evt       Pointer to the event received from the database discovery module.
     */
    void ble_dfu_c_on_db_disc_evt(ble_dfu_c_t * p_ble_dfu_c, ble_db_discovery_evt_t * p_evt);

    /**@brief     Function for handling BLE events from the SoftDevice.
     *
     * @details   This function handles the BLE events received from the SoftDevice. If a BLE
     *            event is relevant to the DFU module, it is used to update
     *            internal variables and, if necessary, send events to the application.
     *
     * @param[in] p_ble_evt     Pointer to the BLE event.
     * @param[in] p_context     Pointer to the DFU client structure.
     */
    void ble_dfu_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);

    /**@brief Function for enabling remote indication.
     *
     * @param[in,out]   p_ble_dfu_c   Pointer to the Service Changed client structure.
     * @param[in]       enable      True to enable Service Changed remote indication, false to disable.
     *
     * @retval NRF_SUCCESS Operation success.
     * @return             If functions from other modules return errors to this function,
     *                     the @ref nrf_error are propagated.
     */
    uint32_t ble_dfu_c_indication_enable(ble_dfu_c_t * p_ble_dfu_c, bool enable);


    /**@brief Function for sending a string to the server.
     *
     * @details This function writes the Buttonless DFU characteristic of the server.
     *
     * @param[in] p_ble_DFU_c Pointer to the DFU client structure.
     * @param[in] p_adv_name  Advertising Name.
     * @param[in] length      Length of the Advertising Name.
     *
     * @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned.
     */
    uint32_t ble_dfu_c_advname_set(ble_dfu_c_t * p_ble_dfu_c, uint8_t * p_adv_name, uint16_t length);


    /**@brief Function for sending a string to the server.
     */
    uint32_t ble_dfu_c_enter_bootloader(ble_dfu_c_t * p_ble_dfu_c);


    /**
     */
    uint32_t ble_dfu_c_handles_assign(ble_dfu_c_t * p_ble_dfu_c, uint16_t conn_handle, ble_dfu_c_handles_t const * p_peer_handles);


#ifdef __cplusplus
}
#endif

#endif // BLE_DFU_C_H__

/** @} */