/* This file was generated by plugin 'Nordic Semiconductor nRF5x v.1.2.2' (BDS version 1.1.3135.0) */

#include "ble_button_test_service.h"
#include <string.h>
#include "nordic_common.h"
#include "ble_srv_common.h"
#include "app_util.h"
#include "app_util_bds.h"

#define OPCODE_LENGTH 1 /**< Length of opcode inside Button test service packet. */
#define HANDLE_LENGTH 2 /**< Length of handle inside Button test service packet. */

/* TODO Consider changing the max values if encoded data for characteristic/descriptor is fixed length */ 
#define MAX_BUTTON_TEST_SERVICE_NEW_CHARACTERISTIC_LEN (23 - OPCODE_LENGTH - HANDLE_LENGTH) /**< Maximum size of a transmitted Button test service new characteristic. */

/**@brief Function for encoding Button test service new characteristic.
 *
 * @param[in]   p_button_test_service_new_characteristic              Button test service new characteristic characteristic structure to be encoded.
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t button_test_service_new_characteristic_encode(ble_button_test_service_button_test_service_new_characteristic_t * p_button_test_service_new_characteristic, uint8_t * encoded_buffer)
{
    uint8_t len = 0; 
    encoded_buffer[len++] = p_button_test_service_new_characteristic->button_field;
    return len;
}

/**@brief Function for decoding Button test service new characteristic.
 *
 * @param[in]   data_len              Length of the field to be decoded.
 * @param[in]   p_data                Buffer where the encoded data is stored.
 * @param[out]  p_write_val           Decoded data.
 *
 * @return      Length of the decoded field.
 */
static uint8_t button_test_service_new_characteristic_decode(uint8_t data_len, uint8_t * p_data, ble_button_test_service_button_test_service_new_characteristic_t * p_write_val)
{
    uint8_t pos = 0;
    p_write_val->button_field = p_data[pos++]; 

    return pos;
} 

/**@brief Function for handling the Connect event.
 *
 * @param[in]   p_button_test_service       Button test service Service structure.
 * @param[in]   p_ble_evt   Event received from the BLE stack.
 */
static void on_connect(ble_button_test_service_t * p_button_test_service, ble_evt_t * p_ble_evt)
{
    p_button_test_service->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}

/**@brief Function for handling the Disconnect event.
 *
 * @param[in]   p_button_test_service       Button test service Service structure.
 * @param[in]   p_ble_evt   Event received from the BLE stack.
 */
static void on_disconnect(ble_button_test_service_t * p_button_test_service, ble_evt_t * p_ble_evt)
{
    UNUSED_PARAMETER(p_ble_evt);
    p_button_test_service->conn_handle = BLE_CONN_HANDLE_INVALID;
}

/**@brief Function for handling the Write event.
 *
 * @param[in]   p_button_test_service       Button test service Service structure.
 * @param[in]   p_ble_evt   Event received from the BLE stack.
 */
static void on_write(ble_button_test_service_t * p_button_test_service, ble_gatts_evt_write_t * p_ble_evt)
{
    
    if(p_ble_evt->handle == p_button_test_service->button_test_service_new_characteristic_handles.value_handle)
    {
        if(p_button_test_service->evt_handler != NULL)
        {
            ble_button_test_service_evt_t evt;
            evt.evt_type = BLE_BUTTON_TEST_SERVICE_BUTTON_TEST_SERVICE_NEW_CHARACTERISTIC_EVT_WRITE;
            button_test_service_new_characteristic_decode(p_ble_evt->len, p_ble_evt->data, &evt.params.button_test_service_new_characteristic);
            p_button_test_service->evt_handler(p_button_test_service, &evt);
        }
    }
}

/**@brief Authorize WRITE request event handler.
 *
 * @details Handles WRITE events from the BLE stack.
 *
 * @param[in]   p_sc_ctrlpt  SC Ctrlpt structure.
 * @param[in]   p_gatts_evt  GATTS Event received from the BLE stack.
 *
 */
static void on_rw_authorize_request(ble_button_test_service_t * p_button_test_service, ble_gatts_evt_t * p_gatts_evt)
{
    ble_gatts_evt_rw_authorize_request_t * p_auth_req = &p_gatts_evt->params.authorize_request;
    if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
    {
        if (   (p_gatts_evt->params.authorize_request.request.write.op
                != BLE_GATTS_OP_PREP_WRITE_REQ)
            && (p_gatts_evt->params.authorize_request.request.write.op
                != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
            && (p_gatts_evt->params.authorize_request.request.write.op
                != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
           )
        {
        
            if (p_auth_req->request.write.handle == p_button_test_service->button_test_service_new_characteristic_handles.value_handle)
            {
                on_write(p_button_test_service, &p_auth_req->request.write);
            }
        }
    }
}

/**@brief Function for handling BLE events.
 *
 * @param[in]   p_button_test_service       Button test service Service structure.
 * @param[in]   p_ble_evt   Event received from the BLE stack.
 */
void ble_button_test_service_on_ble_evt(ble_button_test_service_t * p_button_test_service, ble_evt_t * p_ble_evt)
{
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_button_test_service, p_ble_evt);
            break;
        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_button_test_service, p_ble_evt);
            break;
        case BLE_GATTS_EVT_WRITE:
            on_write(p_button_test_service, &p_ble_evt->evt.gatts_evt.params.write);
            break;
         case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            on_rw_authorize_request(p_button_test_service, &p_ble_evt->evt.gatts_evt);
            break;
        default:
            //No implementation needed.
            break;
    }
}

/**@brief Function for initializing the Button test service. */
uint32_t ble_button_test_service_init(ble_button_test_service_t * p_button_test_service, const ble_button_test_service_init_t * p_button_test_service_init)
{
    uint32_t err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure
    p_button_test_service->evt_handler = p_button_test_service_init->evt_handler;
    p_button_test_service->conn_handle = BLE_CONN_HANDLE_INVALID;
    
    BLE_UUID_BLE_ASSIGN(ble_uuid, 0xA041);
        
    // Add service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_button_test_service->service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    // Add Button test service new characteristic characteristic
    ble_button_test_service_button_test_service_new_characteristic_t button_test_service_new_characteristic_initial_value = p_button_test_service_init->ble_button_test_service_button_test_service_new_characteristic_initial_value; 

    uint8_t button_test_service_new_characteristic_encoded_value[MAX_BUTTON_TEST_SERVICE_NEW_CHARACTERISTIC_LEN];
    ble_add_char_params_t add_button_test_service_new_characteristic_params;
    memset(&add_button_test_service_new_characteristic_params, 0, sizeof(add_button_test_service_new_characteristic_params));
    
    add_button_test_service_new_characteristic_params.uuid                = 0x94DE; 
    add_button_test_service_new_characteristic_params.max_len             = MAX_BUTTON_TEST_SERVICE_NEW_CHARACTERISTIC_LEN;
    add_button_test_service_new_characteristic_params.init_len            = button_test_service_new_characteristic_encode(&button_test_service_new_characteristic_initial_value, button_test_service_new_characteristic_encoded_value);
    add_button_test_service_new_characteristic_params.p_init_value        = button_test_service_new_characteristic_encoded_value; 
    add_button_test_service_new_characteristic_params.char_props.read     = 1; 
    add_button_test_service_new_characteristic_params.read_access         = SEC_OPEN; 
    add_button_test_service_new_characteristic_params.char_props.write    = 1; 
    add_button_test_service_new_characteristic_params.write_access        = SEC_OPEN; 
    // 1 for variable length and 0 for fixed length.
    add_button_test_service_new_characteristic_params.is_var_len          = 1; 

    err_code = characteristic_add(p_button_test_service->service_handle, &add_button_test_service_new_characteristic_params, &(p_button_test_service->button_test_service_new_characteristic_handles));
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    } 

    return NRF_SUCCESS;
}

/**@brief Function for setting the Button test service new characteristic. */
uint32_t ble_button_test_service_button_test_service_new_characteristic_set(ble_button_test_service_t * p_button_test_service, ble_button_test_service_button_test_service_new_characteristic_t * p_button_test_service_new_characteristic)
{
    ble_gatts_value_t gatts_value;
    uint8_t encoded_value[MAX_BUTTON_TEST_SERVICE_NEW_CHARACTERISTIC_LEN];

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = button_test_service_new_characteristic_encode(p_button_test_service_new_characteristic, encoded_value);
    gatts_value.offset  = 0;
    gatts_value.p_value = encoded_value;

    return sd_ble_gatts_value_set(p_button_test_service->conn_handle, p_button_test_service->button_test_service_new_characteristic_handles.value_handle, &gatts_value);
}

