
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(BLE_DNS)
#include "ble_custom_dns.h"

#include <stdlib.h>
#include <string.h>
#include "app_error.h"
#include "ble_gatts.h"
#include "ble_srv_common.h"


#define BLE_DNS_SYS_ID_LEN 8  /**< Length of System ID Characteristic Value. */

 
/**@brief Function for handling the Connect event.
 *
 * @param[in]   p_dns		Device Name Service structure.
 * @param[in]   p_ble_evt	Event received from the BLE stack.
 */
static void on_connect( ble_dns_t * p_dns, ble_evt_t const * p_ble_evt )
{
    p_dns->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}
//
 
/**@brief Function for handling the Disconnect event.
 *
 * @param[in]   p_dns   Device Name Service structure.
 * @param[in]   p_ble_evt        Event received from the BLE stack.
 */
static void on_disconnect( ble_dns_t * p_dns, ble_evt_t const * p_ble_evt )
{
    UNUSED_PARAMETER( p_ble_evt );
    p_dns->conn_handle = BLE_CONN_HANDLE_INVALID;
}
//
 
/**@brief Function for handling the Write event.
 *
 * @param[in]   p_dns		Device Name Service structure.
 * @param[in]   p_ble_evt	Event received from the BLE stack.
 */
static void on_write( ble_dns_t * p_dns, ble_evt_t const * p_ble_evt )
{
    ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
	// device id handler
    if		( ( p_evt_write->handle == p_dns->device_name_char_handle.value_handle ) &&
			  ( p_dns->device_name_handler != NULL ) )
    {
        p_dns->device_name_handler( p_dns, p_evt_write->data, p_evt_write->len );
    }
	// group name handler
	else if( ( p_evt_write->handle == p_dns->group_name_char_handle.value_handle ) &&
			 ( p_dns->group_name_handler != NULL ) )
	{
		p_dns->group_name_handler( p_dns, p_evt_write->data, p_evt_write->len );
	}
	// group id handler
	else if( ( p_evt_write->handle == p_dns->group_id_char_handle.value_handle ) &&
			 ( p_dns->group_name_handler != NULL ) )
	{
		p_dns->group_id_handler( p_dns, p_evt_write->data[ 0 ] );
	}
	// subgroup name handler
	else if( ( p_evt_write->handle == p_dns->subgroup_name_char_handle.value_handle ) &&
			 ( p_dns->subgroup_name_handler != NULL ) )
	{
		p_dns->subgroup_name_handler( p_dns, p_evt_write->data, p_evt_write->len );
	}
	// subgroup id handler
	else if( ( p_evt_write->handle == p_dns->subgroup_id_char_handle.value_handle ) &&
			 ( p_dns->subgroup_name_handler != NULL ) )
	{
		p_dns->subgroup_id_handler( p_dns, p_evt_write->data[ 0 ] );
	}
}
//

/**@brief Function for handling the Write event.
 *
 * @param[in]   p_dns		Device Name Service structure.
 * @param[in]   p_ble_evt	Event received from the BLE stack.
 */
void ble_dns_on_ble_evt( ble_evt_t const * p_ble_evt, void * p_context  )
{
	ble_dns_t * p_dns = ( ble_dns_t * )p_context;
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect( p_dns, p_ble_evt);
            break;
            
        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect( p_dns, p_ble_evt);
            break;
            
        case BLE_GATTS_EVT_WRITE:
            on_write( p_dns, p_ble_evt);
            break;
            
        default:
            // No implementation needed.
            break;
    }
}
//

/**@brief Function for adding our new characterstic to "Device Name Service" that we initiated in the previous tutorial. 
 *
 * @param[in]   p_our_service        Device Name structure.
 *
 */

static uint32_t char_add( uint16_t 						  uuid,
						  uint16_t 						  service_handle,
						  uint8_t 						  uuid_type,
						  uint8_t 					    * p_char_value,
						  uint16_t						  char_len,
						  ble_srv_security_mode_t const * dist_attr_md,
						  ble_gatts_char_handles_t	    * p_handles )
{
	APP_ERROR_CHECK_BOOL( char_len > 0 );
	APP_ERROR_CHECK_BOOL( p_char_value != NULL );
	
	uint32_t err_code;
	
	ble_uuid_t char_uuid;
	
	ble_uuid128_t base_uuid = BLE_UUID_DNS_BASE_UUID;
	
	char_uuid.type = uuid_type;
	char_uuid.uuid = uuid;
	
	err_code = sd_ble_uuid_vs_add( &base_uuid, &char_uuid.type );
	APP_ERROR_CHECK( err_code );
	
	ble_gatts_char_md_t char_md;
    memset( &char_md, 0, sizeof( char_md ) );
	
    char_md.char_props.read  = 1;
	char_md.char_props.write = 1;
	
	ble_gatts_attr_md_t attr_md;
	memset( &attr_md, 0, sizeof( attr_md ) );
    attr_md.read_perm  = dist_attr_md->read_perm;
    attr_md.write_perm = dist_attr_md->write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;

	ble_gatts_attr_t attr_char_value;
    memset( &attr_char_value, 0, sizeof( attr_char_value ) );
	
	attr_char_value.p_uuid		= &char_uuid;
	attr_char_value.p_attr_md 	= &attr_md;
	
	attr_char_value.init_len	= char_len;
	
	attr_char_value.max_len		= char_len;
	attr_char_value.p_value		= p_char_value;
	
    return sd_ble_gatts_characteristic_add( service_handle, &char_md, &attr_char_value, p_handles );
}
//

uint32_t ble_dns_init( ble_dns_t * p_dns, ble_dns_init_t const * p_dns_init )
{
	uint32_t 		err_code;
	ble_uuid_t 		ble_uuid;
	ble_uuid128_t	base_uuid = BLE_UUID_DNS_BASE_UUID;
	
//	APP_ERROR_CHECK_BOOL( p_dns_init->data_io_handler != NULL );		/**< Check if NULL pointer */
//	APP_ERROR_CHECK_BOOL( p_dns_init->group_name_str.length > 0 );		/**< Check if group name is entered */
//	APP_ERROR_CHECK_BOOL( p_dns_init->device_name_str.length > 0 );		/**< Check if device name is entered */
//	APP_ERROR_CHECK_BOOL( p_dns_init->subgroup_name_str.length > 0 );	/**< Check if subgroup name is entered */
	
	// Add service
	err_code = sd_ble_uuid_vs_add( &base_uuid, &p_dns->uuid_type );
	APP_ERROR_CHECK( err_code );
	
//	ble_uuid.type = p_dns->uuid_type;
	ble_uuid.uuid = DNS_UUID_SERVICE;
	
	err_code = sd_ble_gatts_service_add( BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_dns->service_handle );
	APP_ERROR_CHECK( err_code );
	
	// Add Device name characteristic
	err_code = char_add( DNS_UUID_DEVICE_NAME_CHAR,
						 p_dns->service_handle,
						 p_dns->uuid_type,
						 p_dns_init->device_name_str.p_str,
						 p_dns_init->device_name_str.length,
						&p_dns_init->dns_attr_md,
						&p_dns->device_name_char_handle );
						 
	APP_ERROR_CHECK( err_code );
	
	// Add group name characteristic
	err_code = char_add( DNS_UUID_GROUP_NAME_STRING_CHAR,
						 p_dns->service_handle,
						 p_dns->uuid_type,
						 p_dns_init->group_name_str.p_str,
						 p_dns_init->group_name_str.length,
						&p_dns_init->dns_attr_md,
						&p_dns->group_name_char_handle );
	
	APP_ERROR_CHECK( err_code );

	// Add Group id characteristic
	uint8_t group_id[ 2 ] = { p_dns_init->group_id, 0 };
	err_code = char_add( DNS_UUID_GROUP_ID_CHAR,
						 p_dns->service_handle,
						 p_dns->uuid_type,
						 group_id,
						 sizeof( p_dns_init->group_id ),
						&p_dns_init->dns_attr_md,
						&p_dns->group_id_char_handle );
	
	APP_ERROR_CHECK( err_code );

	// Add subgroup name characteristic
//	err_code = char_add( DNS_UUID_SUBGROUP_NUMBER_STRING_CHAR,
//						 p_dns->service_handle,
//						 p_dns->uuid_type,
//						 p_dns_init->subgroup_name_str.p_str,
//						 p_dns_init->subgroup_name_str.length,
//						&p_dns_init->dns_attr_md,
//						&p_dns->subgroup_name_char_handle );
//	
//	APP_ERROR_CHECK( err_code );

//	// Add subroup id characteristic
//	uint8_t subgroup_id[ 2 ] = { p_dns_init->subgroup_id, 0 };
//	err_code = char_add( DNS_UUID_SUBGROUP_ID_CHAR,
//						 p_dns->service_handle,
//						 p_dns->uuid_type,
//						 subgroup_id,
//						 sizeof( p_dns_init->subgroup_id ),
//						&p_dns_init->dns_attr_md,
//						&p_dns->subgroup_id_char_handle );
//	
//	APP_ERROR_CHECK( err_code );

	return NRF_SUCCESS;
}


#endif // CUSTOM_SERVICE_ENABLED(BLE_DNS)
