/*
 * C
 *
 * Copyright 2024-2025 MicroEJ Corp.
 * Use of this source code is governed by a BSD-style license that can be found with this software.
 */

/**
 * @file bt_event.h
 * @brief Bluetooth event implementation.
 * @author MicroEJ Developer Team
 * @version 1.0.0
 * @date 10 October 2024
 */

#ifndef BT_EVENT_H
#define BT_EVENT_H

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sni.h"
#include "LLBLUETOOTH_defines.h"
#include "LLBLUETOOTH_impl.h"
#include <acts_bluetooth/bluetooth.h>
#include <acts_bluetooth/hci.h>
#include <acts_bluetooth/conn.h>
#include <acts_bluetooth/uuid.h>
#include <acts_bluetooth/gatt.h>
#include "conn_internal.h"
#include "att_internal.h"

#ifdef __cplusplus
extern "C" {
#endif

/** @brief Structure describing an event passing through the queue. */
typedef struct bt_event_info_t {
	LLBLUETOOTH_event_t *event;
	uint32_t size;
} bt_event_info_t;

/**
 *  @brief Free the dynamic memory that holds an event.
 *  @param  event   Event to free
 */
void bt_event_free(LLBLUETOOTH_event_t *event);

/**
 *  @brief  Gets an event from the event queue
 *  @param  event_info The reference to the event
 *  @return 0 if SUCCESS, error code otherwise
 */
ssize_t bt_event_queue_get(bt_event_info_t *event_info);

/**
 *  @brief Puts an event in the event queue
 *  @param  event_info The reference to the event
 *  @return 0 if SUCCESS, error code otherwise
 */
ssize_t bt_event_queue_put(bt_event_info_t *event_info);

/**
 *  @brief Gets the suspended thread id
 */
int32_t bt_event_get_suspended_thread_id();

/**
 *  @brief Sets the suspended thread id
 */
void bt_event_set_suspended_thread_id(uint16_t thread_id);

/**
 *  @brief Gets the connection reference
 */
struct bt_conn * bt_event_get_connection();

/**
 *  @brief Gets the current connection handle
 */
uint16_t bt_event_get_current_connection_handle();

/**
 *  @brief Puts the pair response in the queue of the bt_event_pairing_accept event
 *
 *  @param data     Value of the pair response
 *
 * 	@return         0 if success, error code otherwise
 */
int bt_event_pairing_request_put(int8_t *data);

/** @brief Query to proceed incoming pairing or not.
 *
 *  On any incoming pairing req/rsp this callback will be called for
 *  the application to decide whether to allow for the pairing to
 *  continue.
 *
 *  The pairing info received from the peer is passed to assist
 *  making the decision.
 *
 *  As this callback is synchronous the application should return
 *  a response value immediately. Otherwise it may affect the
 *  timing during pairing. Hence, this information should not be
 *  conveyed to the user to take action.
 *
 *  The remaining callbacks are not affected by this, but do notice
 *  that other callbacks can be called during the pairing. Eg. if
 *  pairing_confirm is registered both will be called for Just-Works
 *  pairings.
 *
 *  This callback may be unregistered in which case pairing continues
 *  as if the Kconfig flag was not set.
 *
 *  This callback is not called for BR/EDR Secure Simple Pairing (SSP).
 *
 *  @param conn Connection where pairing is initiated.
 *  @param feat Pairing req/resp info.
 */
enum bt_security_err bt_event_pairing_accept(struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat);

/** @brief notify that pairing procedure was complete.
 *
 *  This callback notifies the application that the pairing procedure
 *  has been completed.
 *
 *  @param conn Connection object.
 *  @param bonded Bond information has been distributed during the
 *                pairing procedure.
 */
void bt_event_pairing_complete(struct bt_conn *conn, bool bonded);

/** @brief A new connection has been established.
 *
 *  This callback notifies the application of a new connection.
 *  In case the err parameter is non-zero it means that the
 *  connection establishment failed.
 *
 *  @param conn New connection object.
 *  @param err HCI error. Zero for success, non-zero otherwise.
 *
 *  @p err can mean either of the following:
 *  - @ref BT_HCI_ERR_UNKNOWN_CONN_ID Creating the connection started by
 *    @ref bt_conn_le_create was canceled either by the user through
 *    @ref bt_conn_disconnect or by the timeout in the host through
 *    @ref bt_conn_le_create_param timeout parameter, which defaults to
 *    @option{CONFIG_BT_CREATE_CONN_TIMEOUT} seconds.
 *  - @p BT_HCI_ERR_ADV_TIMEOUT High duty cycle directed connectable
 *    advertiser started by @ref bt_le_adv_start failed to be connected
 *    within the timeout.
 */
void bt_event_connected(struct bt_conn *conn, uint8_t err);

/** @brief A connection has been disconnected.
 *
 *  This callback notifies the application that a connection
 *  has been disconnected.
 *
 *  When this callback is called the stack still has one reference to
 *  the connection object. If the application in this callback tries to
 *  start either a connectable advertiser or create a new connection
 *  this might fail because there are no free connection objects
 *  available.
 *  To avoid this issue it is recommended to either start connectable
 *  advertise or create a new connection using @ref k_work_submit or
 *  increase @option{CONFIG_BT_MAX_CONN}.
 *
 *  @param conn Connection object.
 *  @param reason HCI reason for the disconnection.
 */
void bt_event_disconnected(struct bt_conn *conn, uint8_t reason);

/** @brief The parameters for an LE connection have been updated.
 *
 *  This callback notifies the application that the connection
 *  parameters for an LE connection have been updated.
 *
 *  @param conn Connection object.
 *  @param interval Connection interval.
 *  @param latency Connection latency.
 *  @param timeout Connection supervision timeout.
 */
void bt_event_le_param_updated(struct bt_conn *conn, uint16_t interval,
                               uint16_t latency, uint16_t timeout, uint8_t status);

/**
 *  @brief Puts the read response in the queue of the bt_event_read_request event
 *
 * 	@param value    Value of the read response
 *  @param len      Length of the read response
 * 	@param err      ATT error code.
 *
 * 	@return         0 if success, error code otherwise
 */
int bt_event_read_request_put(const uint8_t *value, uint16_t len, int8_t err);

/** @brief Attribute read callback
 *
 *  The callback can also be used locally to read the contents of the
 *  attribute in which case no connection will be set.
 *
 *  @param conn   The connection that is requesting to read
 *  @param attr   The attribute that's being read
 *  @param buf    Buffer to place the read result in
 *  @param len    Length of data to read
 *  @param offset Offset to start reading from
 *
 *  @return Number fo bytes read, or in case of an error
 *          BT_GATT_ERR() with a specific ATT error code.
 */
ssize_t bt_event_read_request(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len,
                              uint16_t offset);

/**
 *  @brief Puts the write response in the queue of the bt_event_write_request event
 *
 * 	@param data     Value of the write response
 *
 * 	@return         0 if success, error code otherwise
 */
int bt_event_write_request_put(int8_t *data);

/** @brief Attribute write callback
 *
 *  @param conn   The connection that is requesting to write
 *  @param attr   The attribute that's being written
 *  @param buf    Buffer with the data to write
 *  @param len    Number of bytes in the buffer
 *  @param offset Offset to start writing from
 *  @param flags  Flags (BT_GATT_WRITE_*)
 *
 *  @return Number of bytes written, or in case of an error
 *          BT_GATT_ERR() with a specific ATT error code.
 */
ssize_t bt_event_write_request(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len,
                               uint16_t offset, uint8_t flags);

/**
 *  @brief Indicate operation complete callback
 *
 *  @param params Indication params object.
 */
void bt_event_indication_destroy(struct bt_gatt_indicate_params *params);

/** @typedef bt_gatt_indicate_func_t
 *  @brief Indication complete result callback.
 *
 *  @param conn Connection object.
 *  @param params Indication params object.
 *  @param err ATT error code
 */
void bt_event_indication_cb(struct bt_conn *conn, struct bt_gatt_indicate_params *params, uint8_t err);

#ifdef __cplusplus
}
#endif

#endif /* BT_EVENT_H */
