#include "sdk_config.h"
#include "advertising.h"
#include "ble_types.h"
#include "ble_nus.h"
#include "bsp.h"
#include "bsp_btn_ble.h"
#include "error.h"
#include "nrf_log.h"
#include "nrf_sdh_ble.h"

#define APP_ADV_INTERVAL               800             /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION               1800            /**< The advertising duration (180 seconds) in units of 10 milliseconds. */         
#define APP_ADV_FAST_DURATION          0//1800          /**< The advertising duration of fast advertising in units of 10 milliseconds. */
#define APP_ADV_SLOW_DURATION          0//1800          /**< The advertising duration of slow advertising in units of 10 milliseconds. */
#define APP_ADV_FAST_INTERVAL          MSEC_TO_UNITS(500, UNIT_0_625_MS)        /**< The advertising interval (in units of 0.625 ms). The default value corresponds to 25 ms. */
#define APP_ADV_SLOW_INTERVAL          MSEC_TO_UNITS(500, UNIT_0_625_MS)        /**< Slow advertising interval (in units of 0.625 ms). The default value corresponds to 2 seconds. */
#define NUS_SERVICE_UUID_TYPE          BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

BLE_ADVERTISING_DEF(_gAdvertising);  /**< Advertising module instance. */ 

#if 1
static ble_uuid_t _gAdvUuids[]          = {                                         /**< Universally unique service identifier. */ 
    {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};
#else
static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
{
    {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};

#endif

/**@brief Function for putting the chip into sleep mode.
 *
 * @note This function will not return.
 */
static void _sleepModeEnter(void) {
    ret_code_t errCode;
    errCode = bsp_indication_set(BSP_INDICATE_IDLE);
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("bsp_indication_set() failed, errCode=0x%x\n", errCode);
        return;
    }

    // Prepare wakeup buttons.
    errCode = bsp_btn_ble_sleep_mode_prepare();
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("bsp_btn_ble_sleep_mode_prepare() failed, errCode=0x%x\n", errCode);
        return;
    }

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    errCode = sd_power_system_off();
#ifndef DEBUG_NRF    
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("sd_power_system_off() failed, errCode=0x%x\n", errCode);
        return;
    }
#endif
}


/**@brief Function for handling advertising events.
 *
 * @details This function is called for advertising events that are passed to the application.
 *
 * @param[in] ble_adv_evt  Advertising event.
 */
static void _advertisingEvtHandler(ble_adv_evt_t evt) {
    ret_code_t errCode;

    switch (evt) {
        case BLE_ADV_EVT_FAST:
        {    
            NRF_LOG_INFO("BLE_ADV_EVT_FAST");
            errCode = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            if (errCode != NRF_SUCCESS) {
                NRF_LOG_WARNING("bsp_indication_set() failed, errCode=0x%x\n", errCode);
                return;
            }
        }
        break;
                    
        case BLE_ADV_EVT_IDLE:
        {   
            NRF_LOG_INFO("BLE_ADV_EVT_IDLE");
            // _sleepModeEnter();
        }
        break;

        default:
        break;
    }
}

#if 0
int advertisingInit(void) {
    ret_code_t errCode;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance      = false;
    init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    init.advdata.uuids_complete.uuid_cnt = sizeof(_gAdvUuids) / sizeof(_gAdvUuids[0]);
    init.advdata.uuids_complete.p_uuids  = _gAdvUuids;

    init.srdata.uuids_complete.uuid_cnt = sizeof(_gAdvUuids) / sizeof(_gAdvUuids[0]);
    init.srdata.uuids_complete.p_uuids  = _gAdvUuids;

    init.config.ble_adv_whitelist_enabled = false;
    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_FAST_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_FAST_DURATION;
    init.config.ble_adv_slow_enabled  = true;
    init.config.ble_adv_slow_interval = APP_ADV_SLOW_INTERVAL;
    init.config.ble_adv_slow_timeout  = APP_ADV_SLOW_DURATION;
    init.evt_handler = _advertisingEvtHandler;

    errCode = ble_advertising_init(&_gAdvertising, &init);
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("ble_advertising_init() failed errCode=0x%x", errCode);
        return ERROR_ADVERTISING_INITIALIZE_FAIL;
    }

    ble_advertising_conn_cfg_tag_set(&_gAdvertising, APP_BLE_CONN_CFG_TAG);

    return 0;
}
#else
int advertisingInit(void) {
    uint32_t               errCode;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;

    init.srdata.uuids_complete.uuid_cnt = sizeof(_gAdvUuids) / sizeof(_gAdvUuids[0]);
    init.srdata.uuids_complete.p_uuids  = _gAdvUuids;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    init.evt_handler = _advertisingEvtHandler;

    errCode = ble_advertising_init(&_gAdvertising, &init);
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("ble_advertising_init() failed errCode=0x%x", errCode);
        return ERROR_ADVERTISING_INITIALIZE_FAIL;
    }

    ble_advertising_conn_cfg_tag_set(&_gAdvertising, APP_BLE_CONN_CFG_TAG);

    return 0;
}

#endif


ble_adv_modes_config_t advertisingConfigGet(void) {
    ble_adv_modes_config_t config;
    memset(&config, 0, sizeof(ble_adv_modes_config_t));

    config.ble_adv_fast_enabled           = true;
    config.ble_adv_fast_interval          = APP_ADV_INTERVAL;
    config.ble_adv_fast_timeout           = APP_ADV_DURATION;
    config.ble_adv_on_disconnect_disabled = true;

    return config;
}

void advertisingModesConfigSet(void) {
    const ble_adv_modes_config_t config = advertisingConfigGet();
    ble_advertising_modes_config_set(&_gAdvertising, &config);
}    


/* Function for starting advertising. */
int advertisingStart(void) {
//        memset(m_whitelist_peers, PM_PEER_ID_INVALID, sizeof(m_whitelist_peers));
//        m_whitelist_peer_cnt = (sizeof(m_whitelist_peers) / sizeof(pm_peer_id_t));

//        peer_list_get(m_whitelist_peers, &m_whitelist_peer_cnt);

//        ret = pm_whitelist_set(m_whitelist_peers, m_whitelist_peer_cnt);
//        APP_ERROR_CHECK(ret);

//        // Setup the device identies list.
//        // Some SoftDevices do not support this feature.
//        ret = pm_device_identities_list_set(m_whitelist_peers, m_whitelist_peer_cnt);
//        if (ret != NRF_ERROR_NOT_SUPPORTED)
//        {
//            APP_ERROR_CHECK(ret);
//        }


    const ret_code_t errCode = ble_advertising_start(&_gAdvertising, BLE_ADV_MODE_FAST);
    if (errCode != NRF_SUCCESS) {
        NRF_LOG_WARNING("ble_advertising_start() failed errCode=0x%x", errCode);
        return ERROR_ADVERTISING_START_FAIL;
    }
    
    return 0;
}

