#ifndef _API_WIRELESS_H
#define _API_WIRELESS_H


/**
 * @format 216
 * @param  con_handle
 * @param  address_type
 * @param  address
 */
#define WIRELESS_EVENT_CONNECTED                0x10

/**
 * @format 21
 * @param  con_handle
 * @param  disc_reason
 */
#define WIRELESS_EVENT_DISCONNECTED             0x11

/**
 * @format 11611N
 * @param  advertising_event_type
 * @param  address_type
 * @param  address
 * @param  rssi
 * @param  data_length
 * @param  data
 */
#define WIRELESS_EVENT_ADV_REPORT               0x12

/**
 * @format 1
 * @param  reason
 *      @var 0x04: init(page) state timeout.
 *      @var 0x0c: connection command reject.
 *      @var 0x0d: resource limit, bandwidth no enough for new link.
 */
#define WIRELESS_EVENT_INIT_TERMINATED          0x14


typedef void (* wireless_event_callback_t)(uint8_t event_type, uint8_t *packet, uint8_t size);
typedef void (* wireless_receive_callback_t)(uint16_t con_handle, uint8_t *packet, uint8_t size);


typedef struct PACKED {
    uint8_t  length;
    uint8_t  type;
    uint8_t  data[];
} wireless_adv_slice_t;

typedef struct PACKED {
    uint8_t  event_type;
    uint8_t  addr_type;
    uint8_t  addr[6];
    int8_t   rssi;
    uint8_t  report_len;
    uint8_t  report[];
} wireless_adv_report_t;

typedef struct PACKED {
    uint8_t  reason;
} wireless_init_terminated_t;

typedef struct {
    uint16_t intv;
    uint8_t  adv_type;
    uint8_t  peer_addr_type;
    uint8_t  peer_addr[6];
    uint8_t  data_len;
    uint8_t  data_buf[31];
} wireless_adv_param_t;

typedef struct {
    uint8_t conn_nb_support;
    uint8_t conn_phy_forced;
} wireless_setup_param_t;


/**
 * @brief  Wireless initialize event callback function registration.
 * @param  handler: callback function which will be trigger when any event happen.
 * @retval None.
 */
void wireless_event_handler_register(wireless_event_callback_t handler);

/**
 * @brief  Wireless initialize packet data receive callback function registration.
 * @param  handler: callback function which will be trigger when new packet data received.
 * @retval None.
 */
void wireless_receive_handler_register(wireless_receive_callback_t handler);

/**
 * @brief  Send data according to connection handle.
 * @param  con_handle: connection handle.
 * @param  buf: data buffer need to xfer.
 * @param  size: length of data need to xfer in buf.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_send_for_con(uint16_t con_handle, uint8_t *buf, uint16_t size);

/**
 * @brief  Release rxbuf and prepare for the next reception.
 * @param  buffer: rxbuf, must be generated by the `wireless_receive_handler_register` callback func.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_rxbuf_release(uint8_t *buffer);

/**
 * @brief  Wireless master create a connection by address.
 *         interval, latency and timeout need to meet the follwing relationships:
 *             (timeout * 10) > [(1 + latency) * interval * 1.25 * 2]
 * @param  addr: peer device address.
 * @param  addr_type: peer device address type.
 * @param  interval: 2 - 3200 (unit: 1.25ms).
 *                   4 - 3200 (unit: 1.25ms, more connections).
 * @param  latency: 0 - 499 (unit: intv)
 * @param  timeout: 10 - 3200 (unit: 10ms)
 * @param  init_timeout: 1 - 0xfffffffe (unit: 1ms), and -1L means no timeout. timeout ind see `WIRELESS_EVENT_INIT_TERMINATED`
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_connect_by_addr(uint8_t *addr, uint8_t addr_type, uint16_t interval, uint16_t latency, uint16_t timeout, uint32_t init_timeout);

/**
 * @brief  Wireless set scan param.
 * @param  type: scan type, select the following:
 *             @arg 0: passive scanning.
 *             @arg 1: active scanning.
 * @param  interval: 4 - 16384 (unit: 0.625ms)
 * @param  window: 4 - 16384 (unit: 0.625ms), should <= interval.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_scan_param_set(uint8_t type, uint16_t interval, uint16_t window);

/**
 * @brief  Wireless scan control function.
 * @param  enable: true will start scan if allow, or stop.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_scan_ctrl(bool enable);

/**
 * @brief  Wireless scan state check, async exec by le msg.
 * @retval Return true if scan active, else is stopped.
 */
bool wireless_scan_state_get(void);

/**
 * @brief  Wireless set advertisement param.
 * @param  wireless_adv_param: adv param, see struct "wireless_adv_param_t".
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_adv_param_set(wireless_adv_param_t wireless_adv_param);

/**
 * @brief  Wireless adv control function.
 * @param  enable: true will start adv if allow, or stop.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_adv_ctrl(bool enable);

/**
 * @brief  Wireless adv state check, async exec by le msg.
 * @retval Return true if ADV active, else is stopped.
 */
bool wireless_adv_state_get(void);

/**
 * @brief  Wireless config if prefem a latency.
 * @param  con_handle: connection handle.
 * @param  applied: true will allow wireless perform latency, or disallow.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_latency_applied(uint16_t con_handle, bool applied);

/**
  * @brief  disconnect connection according to connect handle
  * @param  con_handle
  */
int wireless_disconnect(uint16_t con_handle);

/**
  * @brief  Update connection parameter according to connection handle.
  * @param  con_handle: connection handle.
  * @param  intv_min: 2 - 3200(unit: 1.25ms)
  *                   4 - 3200(unit: 1.25ms, more connection)
  * @param  intv_max: 2 - 3200(unit: 1.25ms) interval_min <= interval_max
  *                   4 - 3200(unit: 1.25ms, more connection)
  * @param  lat: 0 - 499 (unit: intv)
  * @param  sup_to: 10 - 3200 (unit: 10ms)
  * @retval Return 0 if OK, other is wrong.
  */
int wireless_conn_update(uint16_t con_handle, uint16_t intv_min, uint16_t intv_max, uint16_t lat, uint16_t sup_to);

/**
 * @brief  Query connection parameter according to connction handle.
 * @param  con_handle: connection handle.
 * @param  intv: return conn interval value.
 * @param  lat: return conn latency value.
 * @param  sup_to: return conn supervise timeout value.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_conn_query(uint16_t con_handle, uint16_t *intv, uint16_t *lat, uint16_t *sup_to);

/**
 * @brief Query maximum transmission unit according to connection handle.
 * @param con_handle: connection handle.
 * @param mtu[out]: return mtu value.
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_mtu_get(uint16_t con_handle, uint8_t *mtu);

/**
 * @brief  Register a function that will be invoke before each active frame start.
 * @param  con_handle: connection handle.
 * @param  callback: callback function when before frame start. It would be voke
 * @retval Return 0 if OK, other is wrong.
 */
int wireless_frame_start_hook_register(uint16_t con_handle, void (*callback)(void));

/**
 * @brief  Initialize wireless module.
 * @param  param: parameter configuration for wireless core setup.
 * @retval None.
 */
void wireless_setup(wireless_setup_param_t const *param);

/**
 * @brief  De-initialize wireless module.
 * @retval None.
 */
void wireless_off(void);

/**
  * @brief  ble fcc test mode config
  * @param  rf_mode: FCC_RF_MODE
  * @param  tx_power: [0,7]
  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
  * @param  phy_type: 0:1M  1:2M
  * @param  todo: 1
  */
int fcc_test_ctrl(fcc_cfg_t *cfg);

/**
 * @brief  Initialize the timer memery pool.
 * @note   This function and a series of related functions are invoked after bt init.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval None.
 */
void bt_alarm_timer_init(void *pool, uint32_t size);

/**
 * @brief  Extend the timer memery pool, it can be used before and after initialization.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval result code.
 */
uint8_t bt_alarm_timer_mem_extend(void *pool, uint32_t size);

/**
 * @brief  Free the timer memery pool, and all timers in the space are released.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval result code.
 */
uint8_t bt_alarm_timer_mem_free(void *pool, uint32_t size);

/**
 * @brief  Start specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_start(uint32_t handle);

/**
 * @brief  Stop specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_stop(uint32_t handle);

/**
 * @brief  Acquire a alarm timer.
 * @param  handle: alarm timer handle.
 * @param  interval: alarm timer trigger interval, unit [1, 0xffffff) ms.
 * @param  is_repeat: trigger mode.
 * @param  callback: callback function.
 * @retval result code.
 */
uint8_t bt_alarm_timer_acquire(uint32_t *handle, uint32_t interval, uint8_t is_repeat, void (*callback)(uint32_t handle));

/**
 * @brief  Release specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_release(uint32_t handle);

/**
 * @brief  Query specified id alarm timer remain time.
 * @param  handle: alarm timer handle.
 * @param  remain: the remain time for specified id alarm timer.
 * @retval result code.
 */
uint8_t bt_alarm_timer_query_time(uint32_t handle, uint32_t *remain);

/**
 * @brief  Modify specified id alarm timer interval, if the timer is start, it
 *         will be re-start after update interval param.
 * @param  handle: alarm timer handle.
 * @param  interval: new interval, unit [1, 0xffffff) ms.
 * @param  is_repeat: new is_repeat mode state.
 * @retval result code.
 */
uint8_t bt_alarm_timer_modify_interval(uint32_t handle, uint32_t interval, uint8_t is_repeat);

/* LPWR API */
void bt_enter_sleep(void);
bool bt_is_sleep(void);
uint32_t bt_sleep_proc(void);
void bt_exit_sleep(void);

#endif // _API_WIRELESS_H
