#include <stdbool.h>
#include <stdint.h>
#include "nordic_common.h"
#include "sdk_config.h"
#include "nrfx_config.h"

#include "app_timer.h"
#include "nrf_delay.h"
#include "boards.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "ble_gap.h"
#include "ble.h"
#include "nrf_sdm.h"
#include "ble_advertising.h"
#include "bsp.h"
#include "nrf_ble_qwr.h"
#include "nrf_sdh.h"
#include "Peer_manager.h"
#include "Fds.h"

#define APP_BLE_OBSERVER_PRIO   3
#define APP_BLE_CONN_CFG_TAG             1                                                       /**< A tag identifying the SoftDevice BLE configuration. */



static void lfclk_config(void)
{
    uint32_t err_code;

    err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_clock_lfclk_request(NULL);
}

// low clock
nrf_clock_lf_cfg_t  const clock_lf_cfg=
{
	.source = NRF_SDH_CLOCK_LF_SRC,
	.rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV,  // CALIBARTE
	.rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
	.accuracy = NRF_SDH_CLOCK_LF_ACCURACY
};

nrf_ble_qwr_t m_qwr;

static void log_init(void)
{
	
	ret_code_t err_code=NRF_LOG_INIT(NULL);
	APP_ERROR_CHECK(err_code);
	NRF_LOG_DEFAULT_BACKENDS_INIT();
	
}

static void timers_init(void)
{
	ret_code_t err_code = app_timer_init();
	APP_ERROR_CHECK(err_code);
}

static void power_management_init(void)
{
	ret_code_t err_code;
	err_code = nrf_pwr_mgmt_init();
	APP_ERROR_CHECK(err_code);
}

static void idle_state_handle(void)
{
	if (NRF_LOG_PROCESS() == false)
	{
		nrf_pwr_mgmt_run();
	}
}

static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context)
{
	ret_code_t err_code = NRF_SUCCESS;
	uint16_t  m_conn_handle;
	
	switch (p_ble_evt->header.evt_id)
	{
		case BLE_GAP_EVT_DISCONNECTED:
			NRF_LOG_INFO("Disconnected");
		  break;
		case BLE_GAP_EVT_CONNECTED:
			NRF_LOG_INFO("connected");
		  err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
		  APP_ERROR_CHECK(err_code);
		  m_conn_handle= p_ble_evt->evt.gap_evt.conn_handle;
		  // assign handle to queue writer
		  err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr,m_conn_handle);
		  APP_ERROR_CHECK(err_code);
		  break;
		case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
		{
			NRF_LOG_DEBUG("PHY update request");
			ble_gap_phys_t  const phys = {
				.rx_phys = BLE_GAP_PHY_AUTO,
				.tx_phys = BLE_GAP_PHY_AUTO,
			};
			err_code =  sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
			APP_ERROR_CHECK(err_code);
		}
			break;
		//GATT client overtime
		case BLE_GATTC_EVT_TIMEOUT:
	
		NRF_LOG_DEBUG("GATT CLIENT TIMEOUT");
		  err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
		   BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
		   
		   APP_ERROR_CHECK(err_code);
		
		  break;
		
		default:
			break;
	}
}

static void ble_stack_init(void)
{
	ret_code_t err_code;
	
	// according to sdk_config.h clock config to set low frequency clock
	err_code = nrf_sdh_enable_request();
	APP_ERROR_CHECK(err_code);
	
	// RAM start
	uint32_t ram_start = 0;
	err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG,&ram_start);
	APP_ERROR_CHECK(err_code);
	
	// enable ble statk
	err_code =  nrf_sdh_ble_enable(&ram_start);
	APP_ERROR_CHECK(err_code);
	
	// register
//	NRF_SDH_BLE_OBSERVER(m_ble_observer,APP_BLE_OBSERVER_PRIO, ble_evt_hander,NULL);
	
	
}
#ifdef DEVICE_NAME
#undef DEVICE_NAME
#endif

#define DEVICE_NAME "TPZQT"

static void gap_params_init(void)
{
	ret_code_t  err_code;
	ble_gap_conn_params_t  gap_conn_params;
	ble_gap_conn_sec_mode_t  sec_mode;
	// security mode ,1 no security
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
	// gap name
	err_code = sd_ble_gap_device_name_set(&sec_mode,
	(const uint8_t *)DEVICE_NAME,
		strlen(DEVICE_NAME));
   APP_ERROR_CHECK(err_code);
	
	memset(&gap_conn_params, 0, sizeof(gap_conn_params));
	gap_conn_params.min_conn_interval = 100;
	gap_conn_params.max_conn_interval = 300;
	gap_conn_params.slave_latency = 5000;
	gap_conn_params.conn_sup_timeout = 5000;
	err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
	APP_ERROR_CHECK(err_code);
}

// GATT init
//NRF_BLE_GATT_DEF(m_gatt);

static void gatt_init(void)
{
	//ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
//	APP_ERROR_CHECK(err_code);
}

//advertising 
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
	ret_code_t err_code;
	switch(ble_adv_evt)
	{
		case BLE_ADV_EVT_FAST:
			NRF_LOG_INFO("FAST ad");
			
		break;
		case BLE_ADV_EVT_IDLE:
			NRF_LOG_DEBUG("adv idle");
		break;
		default:
			break;
	}
	
}
static void advertising_init(void)
{
		ret_code_t err_code;
		ble_advertising_init_t init;
		memset(&init, 0, sizeof(init));
		init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
		init.advdata.include_appearance = true;
		init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
		init.config.ble_adv_fast_enabled = true;
		init.config.ble_adv_fast_interval = 100;
		init.config.ble_adv_fast_timeout = 0;
		init.evt_handler = on_adv_evt;
}

static void nrf_qwr_error_handler(uint32_t code)
{
	NRF_LOG_INFO("qwr  handler");
}

static void services_init(void)
{
	ret_code_t err_code;
	nrf_ble_qwr_init_t qwr_init={0};
	qwr_init.error_handler = nrf_qwr_error_handler;
	err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
	APP_ERROR_CHECK (err_code);
	
}

void  out_log(void)
{
	
//	NRF_LOG_INFO("loop");	
}
int main(void)
{
	log_init();
	timers_init();
	//LINK power_management_init();
	lfclk_config();
	
	out_log();
	while (true)
	{
		idle_state_handle();
	}
}
