#include <stdint.h>
#include <stdbool.h>

#include "app_error.h"
#include "nrf_error.h"
#include "softdevice_handler.h"
#include "nordic_common.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_needlite.h"
#include "ble_dis.h"
#include "ble_conn_params.h"
#include "ble_error_log.h"
#include "ble_bondmngr.h"
#include "ble_debug_assert_handler.h"
#include "nordic_common.h"
#include "nrf.h"
#include "app_error.h"
#include "nrf_gpio.h"
#include "nrf51_bitfields.h"
#include "ble_gap.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_bas.h"
#include "ble_dis.h"
#include "ble_conn_params.h"
#include "boards.h"
#include "ble_sensorsim.h"
#include "softdevice_handler.h"
#include "app_timer.h"
#include "simple_uart.h"
#include "nrf_delay.h"
#include "ble_radio_notification.h"
#include "ble_dfu.h"
#include "dfu_app_handler.h"
#include "device_manager.h"

#include "leds.h"
#include "bluetooth_control.h"
#include "ble_error_log.h"
#include "ble_bondmngr.h"
#include "ble_debug_assert_handler.h"
#include "pstorage.h"

#include "device_config.h"
#include "debug_util.h"
#include "version.h"
#include "configuration.h"
#include "board.h"

#define DEVICE_NAME                         "needlite"                                /**< Name of device. Will be included in the advertising data. */
#define MANUFACTURER_NAME                   "needlite ApS"                            /**< Manufacturer. Will be passed to Device Information Service. */
#define MODEL_NUMBER                        "needlite 1.0.0"                          /**< Prototype. Will be passed to Device Information Service. */
#define APP_ADV_INTERVAL                    MSEC_TO_UNITS(50, UNIT_0_625_MS)         /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */
#define APP_ADV_TIMEOUT_IN_SECONDS          20                                        /**< The advertising timeout in units of seconds. */

#define INTENSITY_TYPE                      0x01
#define ONOFF_TYPE                          0x02
#define USERNAME_TYPE                       0x03


#define BLE_UUID_needlite_SERVICE           0x9418

#define MIN_CONN_INTERVAL                   MSEC_TO_UNITS(10, UNIT_1_25_MS)           /**< Minimum acceptable connection interval (0.5 seconds). */
#define MAX_CONN_INTERVAL                   MSEC_TO_UNITS(50, UNIT_1_25_MS)          /**< Maximum acceptable connection interval (1 second). */
#define SLAVE_LATENCY                       0                                          /**< Slave latency. */
#define CONN_SUP_TIMEOUT                    MSEC_TO_UNITS(4000, UNIT_10_MS)           /**< Connection supervisory timeout (4 seconds). */

#define FIRST_CONN_PARAMS_UPDATE_DELAY       APP_TIMER_TICKS(50, app_timer_prescaler) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY        APP_TIMER_TICKS(50, app_timer_prescaler) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT         3                                          /**< Number of attempts before giving up the connection parameter negotiation. */

#define SEC_PARAM_TIMEOUT                    30                                         /**< Timeout for Pairing Request or Security Request (in seconds). */
#define SEC_PARAM_BOND                       1                                          /**< Perform bonding. */
#define SEC_PARAM_MITM                       0                                          /**< Man In The Middle protection not required. */
#define SEC_PARAM_IO_CAPABILITIES            BLE_GAP_IO_CAPS_NONE                       /**< No I/O capabilities. */
#define SEC_PARAM_OOB                        0                                          /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE               7                                          /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE               16                                         /**< Maximum encryption key size. */

#define DEAD_BEEF                            0xDEADBEEF                                 /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */


char mac_address[20] = { 0 };

static uint8_t bt_brightness_data = NO_BRIGHTNESS_CHANGE;
static bool    bt_brightness_data_flag = false;

static bool bt_onoff_data_flag = false;
static uint8_t bt_onoff_data = 0;

static  uint16_t                              m_conn_handle = BLE_CONN_HANDLE_INVALID;   /**< Handle of the current connection. */
static  ble_gap_sec_params_t                  m_sec_params;                              /**< Security requirements for this application. */
static  ble_gap_adv_params_t                  m_adv_params;                              /**< Parameters to be passed to the stack when starting advertising. */
static  ble_needlite_t                        m_needlite;

static ble_dfu_t                              m_dfus;
static dm_application_instance_t              m_app_handle;

static uint8_t disconnect_reason = 0; // Stores the reason why the last disconnect occured, BT core spec page 590

static volatile bool current_radio_active_state = false;

int8_t rssi_result = 100;
uint8_t rssi_ready = 0;

static uint8_t ignore_rssi_flag = 0;

static bool bt_connected = false;
static uint32_t app_timer_prescaler = 0;

static void advertising_init(void);

bool is_bt_connected(void)
{
    return bt_connected;
}

/**@brief Function for handling the Device Manager events.
 *
 * @param[in]   p_evt   Data associated to the device manager event.
 */
static uint32_t device_manager_evt_handler(dm_handle_t const    * p_handle,
        dm_event_t const     * p_event,
        api_result_t           event_result)
{
    APP_ERROR_CHECK(event_result);
    return NRF_SUCCESS;
}

void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
    app_error_handler(DEAD_BEEF, line_num, p_file_name);

}

char str[100];

void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
    nrf_delay_ms(1);
    simple_uart_put(error_code>>24);
    nrf_delay_ms(1);
    simple_uart_put(error_code>>16);
    nrf_delay_ms(1);
    simple_uart_put(error_code>>8);
    nrf_delay_ms(1);
    simple_uart_put(error_code);
    nrf_delay_ms(1);

    // This call can be used for debug purposes during application development.
    // @note CAUTION: Activating this code will write the stack to flash on an error.
    //                This function should NOT be used in a final product.
    //                It is intended STRICTLY for development/debugging purposes.
    //                The flash write will happen EVEN if the radio is active, thus interrupting
    //                any communication.
    //                Use with care. Uncomment the line below to use.
    // ble_debug_assert_handler(error_code, line_num, p_file_name);

    // On assert, the system can only recover with a reset.
    NVIC_SystemReset();
}

static void set_device_name(const char * name, uint8_t update_adv)
{
    uint32_t retval;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    retval = sd_ble_gap_device_name_set(&sec_mode,
                                        (const uint8_t *) name,
                                        strlen(name));

    if (update_adv) {
        // Initialize advertising data after device name change
        advertising_init();
    }

    APP_ERROR_CHECK(retval);
}

/**@brief Function for starting advertising.
 */
void advertising_start(void)
{
    uint32_t err_code;
    m_adv_params.interval = APP_ADV_INTERVAL;
    sd_ble_gap_adv_stop();
    err_code = sd_ble_gap_adv_start(&m_adv_params);
    APP_ERROR_CHECK(err_code);
}

// Function for handling the Application's BLE Stack events.
// p_ble_evt   Bluetooth stack event.
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
    uint32_t                         err_code;
    static ble_gap_evt_auth_status_t m_auth_status;
    ble_gap_enc_info_t *             p_enc_info;

    static int32_t rssi;
    static int32_t rssi_temp;

    static uint8_t filter_cnt;
	
    switch (p_ble_evt->header.evt_id) {
    case BLE_GAP_EVT_CONNECTED:
        bt_connected = true;
        m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        sd_ble_gap_rssi_start(m_conn_handle);
        debug_printf("BLE connected\n\r");
        break;

    case BLE_GAP_EVT_DISCONNECTED:
        bt_connected = false;
        m_conn_handle = BLE_CONN_HANDLE_INVALID;
        sd_ble_gap_rssi_stop(m_conn_handle);
        advertising_start();
        disconnect_reason = p_ble_evt->evt.gap_evt.params.disconnected.reason;
        debug_printf("BLE disconnected, reason: 0x%02X\n\r", disconnect_reason);
        event_log_stop_sending();
        break;

    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
        err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                               BLE_GAP_SEC_STATUS_SUCCESS,
                                               &m_sec_params);
        APP_ERROR_CHECK(err_code);
        break;

    case BLE_GATTS_EVT_SYS_ATTR_MISSING:
        err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
        APP_ERROR_CHECK(err_code);
        break;

    case BLE_GAP_EVT_AUTH_STATUS:
        m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status;
        break;

    case BLE_GAP_EVT_SEC_INFO_REQUEST:
        p_enc_info = &m_auth_status.periph_keys.enc_info;
        if (p_enc_info->div == p_ble_evt->evt.gap_evt.params.sec_info_request.div) {
            err_code = sd_ble_gap_sec_info_reply(m_conn_handle, p_enc_info, NULL);
            APP_ERROR_CHECK(err_code);
        } else {
            // No keys found for this device
            err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL);
            APP_ERROR_CHECK(err_code);
        }
        break;

    case BLE_GAP_EVT_TIMEOUT:
        break;
		
    case BLE_GAP_EVT_RSSI_CHANGED:
        rssi_temp = p_ble_evt->evt.gap_evt.params.rssi_changed.rssi;
        rssi = rssi + rssi_temp;
        filter_cnt ++;
        if(filter_cnt == 19) {
            filter_cnt = 0;
            rssi_result = rssi/20;
            rssi_ready = 1;
            //if(rssi_result >= (int8_t)190) ignore_rssi_flag = 0;
            rssi = rssi_result;
            //debug_printf("%d,", rssi_result, ignore_rssi_flag);
        }
        //sd_ble_gap_rssi_stop(m_conn_handle);
        break;

    default:
        // No implementation needed.
        break;
    }
}

void start_rssi()
{
    sd_ble_gap_rssi_start(m_conn_handle);

}

void ignore_rssi()
{
    ignore_rssi_flag = 1;

}

uint8_t get_rssi(void)
{

    if(ignore_rssi_flag == 0) return rssi_result;
    else return 200;
}

/**@brief Function for initializing the Advertising functionality.
 *
 * @details Encodes the required advertising data and passes it to the stack.
 *          Also builds a structure to be passed to the stack when starting advertising.
 */
static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    ble_uuid_t adv_uuids[] = {{NEEDLITE_UUID_SERVICE,         0x01}};

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance      = true;
    advdata.flags.size              = sizeof(flags);
    advdata.flags.p_data            = &flags;
    advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    advdata.uuids_complete.p_uuids  = adv_uuids;

    err_code = ble_advdata_set(&advdata, NULL);
    APP_ERROR_CHECK(err_code);

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
    m_adv_params.p_peer_addr = NULL;                           // Undirected advertisement.
    m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval    = APP_ADV_INTERVAL;
    m_adv_params.timeout     = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;


}

// Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
// This function is called from the BLE Stack event interrupt handler after a BLE stack
// event has been received.
//
// p_ble_evt   Bluetooth stack event.
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
    dm_ble_evt_handler(p_ble_evt);
    ble_needlite_on_ble_evt(&m_needlite, p_ble_evt);
    ble_conn_params_on_ble_evt(p_ble_evt);
    ble_dfu_on_ble_evt(&m_dfus, p_ble_evt);
    on_ble_evt(p_ble_evt);
}

// Function for dispatching a system event to interested modules.
//
// This function is called from the System event interrupt handler after a system
// event has been received.
//
// sys_evt   System stack event.
static void sys_evt_dispatch(uint32_t sys_evt)
{
    pstorage_sys_event_handler(sys_evt);
}

// Function for initializing the BLE stack.
// Initializes the SoftDevice and the BLE event interrupt.
static void ble_stack_init(void)
{
    uint32_t err_code;

    ble_gap_addr_t                   addr;

    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
    //SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION , false);

    ble_enable_params_t ble_enable_params;
    memset(&ble_enable_params, 0, sizeof(ble_enable_params));
    ble_enable_params.gatts_enable_params.service_changed = 0;
    err_code = sd_ble_enable(&ble_enable_params);

    // Generate an unique address by inverting the first byte of 
    // the original address
    sd_ble_gap_address_get(&addr);
    addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
    addr.addr[0] = ~addr.addr[0];
    sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr);  
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);

}

static void device_manager_init(void)
{
    uint32_t                err_code;
    dm_init_param_t         init_data;
    dm_application_param_t  register_param;

    // Initialize persistent storage module.
    err_code = pstorage_init();
    APP_ERROR_CHECK(err_code);

    err_code = dm_init(&init_data);
    APP_ERROR_CHECK(err_code);

    memset(&register_param.sec_param, 0, sizeof(ble_gap_sec_params_t));

    register_param.sec_param.timeout      = SEC_PARAM_TIMEOUT;
    register_param.sec_param.bond         = SEC_PARAM_BOND;
    register_param.sec_param.mitm         = SEC_PARAM_MITM;
    register_param.sec_param.io_caps      = SEC_PARAM_IO_CAPABILITIES;
    register_param.sec_param.oob          = SEC_PARAM_OOB;
    register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
    register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
    register_param.evt_handler            = device_manager_evt_handler;
    register_param.service_type           = DM_PROTOCOL_CNTXT_GATT_SRVR_ID;

    err_code = dm_register(&m_app_handle, &register_param);
    APP_ERROR_CHECK(err_code);
}

// Function for the GAP initialization.
// This function sets up all the necessary GAP (Generic Access Profile) parameters of the
// device including the device name, appearance, and the preferred connection parameters.
static void gap_params_init(void)
{
    uint32_t                err_code;
    ble_gap_conn_params_t   gap_conn_params;


    device_config_t * config = device_config_get();
    set_device_name(config->display_name, 0);

    err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN); // Sets logo on computer
    APP_ERROR_CHECK(err_code);

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
}

void led_state(ble_needlite_t * p_needlite, uint8_t led_state)
{
    bt_onoff_data_flag = true;
	
	if (led_state != LAMP_ON && led_state != LAMP_OFF) {
		led_state = LAMP_OFF;
	}
	
    bt_onoff_data = led_state;
}

void led_brightness(ble_needlite_t * p_needlite, uint8_t brightness)
{
    bt_brightness_data_flag = true;
	
	// Check limits 
	if (brightness > PWM_NORM_MAX) {
		brightness = PWM_NORM_MAX;
	}
	if (brightness < PWM_NORM_MIN) {
		brightness = PWM_NORM_MIN;
	}
	
    bt_brightness_data = brightness;
}

/**
 * Handler for a write to the `displayname` characteristic.
 */
void set_displayname(ble_needlite_t * p_needlite, uint8_t * data, uint32_t len)
{
    // Make sure name is a null-terminated string,
    // so copy to temporary buffer
    char name[MAX_DISPLAY_NAME_LENGTH] = {0};
    strncpy(name, (const char *) data, len);

    //debug_printf("name: %s\n\r", name);
    device_config_update_name(name);
    set_device_name(name, 1);
}

uint8_t get_bt_brightness(void)
{
    if(bt_brightness_data_flag == true) {
        bt_brightness_data_flag = false;
        return bt_brightness_data;
    }
    
    return NO_BRIGHTNESS_CHANGE;
}

enum new_lamp_state_t get_bt_onoff(void)
{
    if(bt_onoff_data_flag == true) {
        bt_onoff_data_flag = false;
        if (bt_onoff_data == 0){
            return LAMP_STATE_OFF;
        } else if (bt_onoff_data == 1){
            return LAMP_STATE_ON;
        }
        return LAMP_STATE_UNKNOWN;
    }
    return LAMP_STATE_NO_CHANGE;
}

void set_bt_led_level(uint8_t local_app_data)
{
    ble_lbs_brightness_change(&m_needlite, local_app_data);
}

void set_bt_led_state(uint8_t local_app_data)
{
    ble_lbs_onoff_change(&m_needlite, local_app_data);
}
void broadcast_proximity()
{
    int8_t rssi = (int8_t) rssi_result;
    ble_lbs_proximity_change(&m_needlite, rssi);
}

uint32_t bluetooth_send_event(event_log_entry_t * event) 
{
    event_log_packet_t packet;
    packet.entry = *event;
    packet.now = event_clock_get();
    return ble_lbs_event_data_send(&m_needlite, &packet);
}

static void advertising_stop(void)
{
    uint32_t err_code;

    err_code = sd_ble_gap_adv_stop();
    APP_ERROR_CHECK(err_code);

}

static void reset_prepare(void)
{
    uint32_t err_code;

    if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
        // Disconnect from peer.
        err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        APP_ERROR_CHECK(err_code);
    } else {
        // If not connected, then the device will be advertising. Hence stop the advertising.
        advertising_stop();
    }
    debug_printf("RESET\n\r");
    set_lamp_state(LED_BOOTLOADER); // Set slave and master leds fully on. We do it here to avoid including the one-wire-interface in the bootloader

    err_code = ble_conn_params_stop();
    APP_ERROR_CHECK(err_code);
}

// Function for initializing services that will be used by the application.
static void services_init(void)
{
    uint32_t       err_code;
    ble_needlite_init_t needlite_init;
    ble_dis_init_t dis_init; // device information service

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
    ble_srv_ascii_to_utf8(&dis_init.model_num_str, (char *)MODEL_NUMBER);
    ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, (char *) needlite_get_version());
    ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, (char *) board_rev_get_str());

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);


    // Initialize Needlite Service.
    memset(&needlite_init, 0, sizeof(needlite_init));

    // Default values
    needlite_init.initial_led_level = get_norm_from_duty_cycle(
		get_initial_duty_cycle());
    needlite_init.initial_on_off_state = LAMP_OFF;

    err_code = ble_needlite_init(&m_needlite, &needlite_init);
    APP_ERROR_CHECK(err_code);

    ble_dfu_init_t dfus_init;
    memset(&dfus_init, 0, sizeof(dfus_init));
    dfus_init.evt_handler    = dfu_app_on_dfu_evt;
    dfus_init.error_handler  = NULL;
    err_code = ble_dfu_init(&m_dfus, &dfus_init);
    APP_ERROR_CHECK(err_code);

    dfu_app_reset_prepare_set(reset_prepare);
}

// Function for handling the Connection Parameters Module.
//    This function will be called for all events in the Connection Parameters Module which
//    are passed to the application.
//
//    All this function does is to disconnect. This could have been done by simply
//    setting the disconnect_on_fail config parameter, but instead we use the event
//    handler mechanism to demonstrate its use.
// p_evt   Event received from the Connection Parameters Module.
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
    uint32_t err_code;

    if(p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
        err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
        APP_ERROR_CHECK(err_code);
    }
}

// Function for handling a Connection Parameters error.
// nrf_error   Error code containing information about what went wrong.
static void conn_params_error_handler(uint32_t nrf_error)
{
    APP_ERROR_HANDLER(nrf_error);
}

// Function for initializing the Connection Parameters module.
static void conn_params_init(void)
{
    uint32_t               err_code;
    ble_conn_params_init_t cp_init;

    memset(&cp_init, 0, sizeof(cp_init));

    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;//m_hrs.hrm_handles.cccd_handle;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;

    err_code = ble_conn_params_init(&cp_init);
    APP_ERROR_CHECK(err_code);
}

// Function for initializing security parameters.
static void sec_params_init(void)
{
    m_sec_params.timeout      = SEC_PARAM_TIMEOUT;
    m_sec_params.bond         = SEC_PARAM_BOND;
    m_sec_params.mitm         = SEC_PARAM_MITM;
    m_sec_params.io_caps      = SEC_PARAM_IO_CAPABILITIES;
    m_sec_params.oob          = SEC_PARAM_OOB;
    m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
    m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
}

void sd_assertion_handler(uint32_t pc, uint16_t line_num, const uint8_t * file_name)
{
    UNUSED_PARAMETER(pc);
    assert_nrf_callback(line_num, file_name);
}

void ble_on_radio_active_evt(bool radio_active)
{
    current_radio_active_state = radio_active;
}

uint8_t one_wire_go(void)
{
    return current_radio_active_state;
}

uint8_t get_bt_disconnect_reason(void){
    return disconnect_reason;
}

void bluetooth_init(uint32_t app_timer_prescaler_val)
{
    app_timer_prescaler = app_timer_prescaler_val;
    ble_stack_init();
    device_manager_init();
    device_config_init();
    gap_params_init();
    advertising_init();
    services_init();
    conn_params_init();
    sec_params_init();
    advertising_start();
    ble_radio_notification_init(NRF_APP_PRIORITY_HIGH,
                                NRF_RADIO_NOTIFICATION_DISTANCE_4560US,
                                ble_on_radio_active_evt);

}


