/**
 * @file CosmicNotifications.h
 * @brief Notification types and structures for the Cosmic SDK.
 *
 * This header file defines the notification system used by the CosmicSDK to communicate
 * events from the hardware device to the application. It provides structures and enumerations
 * for handling various notification types including I3C Hot-Join, I3C In-Band Interrupts (IBI),
 * GPIO events, and UART data reception.
 *
 * The API is designed to work in both C and C++ environments, with the C++ interface providing
 * convenience methods for parsing and accessing notification payloads.
 *
 * @section Usage
 *
 * In C, use the generic Notification structure with the @b type field to determine
 * the notification category, then cast the @b payload accordingly.
 *
 * In C++, use the convenience methods (i3cHotJoin(), i3cIbi(), uartRx()) to automatically
 * parse and access typed notification data.
 *
 */
#pragma once

#include <stddef.h>
#include <stdint.h>

#include "CosmicSDKExport.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @enum NotificationType
 * @brief Enum to represent the different notification types
 * @ingroup Structures_Notifications
 */
typedef enum {
  NOTIF_I3C_HJ,  /**< I3C Hot-Join Notification */
  NOTIF_I3C_IBI, /**< I3C In-Band Interrupt Notification */
  NOTIF_GPIO,    /**< GPIO Interrupt Notification */
  NOTIF_UART,    /**< UART Rx Notification */
  NOTIF_UNKNOWN  /**< Unknown Notification */
} NotificationType;

/**
 * @struct I3cHotJoinNotification
 * @brief Parsed I3C Hot-Join notification information.
 * @ingroup Structures_Notifications
 */
typedef struct {
  uint8_t pid[6];         /**< Provisional ID (48-bit) reported by the device during Hot-Join. */
  uint8_t bcr;            /**< Bus Characteristics Register value of the joining device. */
  uint8_t dcr;            /**< Device Characteristics Register value of the joining device. */
  uint8_t dynamicAddress; /**< Dynamic address assigned by the controller after Hot-Join. */
} I3cHotJoinNotification;

/**
 * @struct I3cIbiNotification
 * @brief Parsed I3C In-Band Interrupt (IBI) notification information.
 * @ingroup Structures_Notifications
 */
typedef struct {
  uint8_t address;        /**< Dynamic address of the device that generated the IBI. */
  const uint8_t* payload; /**< Pointer to the optional IBI payload data (if present). */
  size_t payloadLength;   /**< Length in bytes of the IBI payload. */
} I3cIbiNotification;

/**
 * @struct UartRxNotification
 * @brief Parsed UART RX notification.
 * This struct holds the data received through the UART.
 * @ingroup Structures_Notifications
 */
typedef struct {
  const uint8_t* data; /**< Pointer to the received UART data buffer. */
  size_t dataLength;   /**< Number of bytes received in the buffer. */
} UartRxNotification;

/**
 * @struct GpioInterruptNotification
 * @brief Parsed GPIO Interrupt notification information.
 * @ingroup Structures_Notifications
 */
typedef struct {
  uint8_t pinNumber; /**< GPIO pin number that triggered the interrupt. */
} GpioInterruptNotification;

#ifdef __cplusplus
}  // extern "C"
#endif

/**
 * @struct Notification
 * @brief Generic notification wrapper used by both C and C++ APIs.
 * @ingroup Structures_Notifications
 *
 * This structure is delivered by callback-based APIs:
 * - C API: @ref CosmicSDK_onNotification
 * - C++ API: @ref CosmicSDK::onNotification
 *
 * The @p type field identifies the notification category. The payload bytes
 * are exposed through @p payload and @p payloadLength.
 *
 * Parsing:
 * - C users should call the dedicated parser helpers:
 *   @ref CosmicSDK_notificationAsI3cHotJoin,
 *   @ref CosmicSDK_notificationAsI3cIbi,
 *   @ref CosmicSDK_notificationAsGpio,
 *   @ref CosmicSDK_notificationAsUartRx.
 * - C++ users can call the convenience methods:
 *   @ref i3cHotJoin, @ref i3cIbi, @ref gpio, @ref uartRx.
 */
typedef struct Notification {
  /**
   * @brief Notification type. See @ref NotificationType for valid values.
   */
  NotificationType type;

  /**
   * @brief Pointer to raw notification payload bytes.
   *
   * The payload format depends on @p type.
   */
  const uint8_t* payload;

  /**
   * @brief Payload size in bytes.
   */
  size_t payloadLength;

#ifdef __cplusplus
  // C++ only convenience methods

  /**
   * @brief Constructs a Notification with the given type and payload.
   * @note C++ only. Not available in the C API.
   *
   * @param t The notification type.
   * @param p Pointer to the notification payload data.
   * @param len Length of the payload data in bytes.
   */
  Notification(NotificationType t, const uint8_t* p, size_t len) noexcept :
      type(t),
      payload(p),
      payloadLength(len) {};

  /**
   * @brief Parses this notification as I3C Hot-Join data.
   * @note C++ only. Not available in the C API.
   *
   * This method validates @p type and payload length before decoding.
   *
   * @return Pointer to parsed @ref I3cHotJoinNotification when this is a valid
   *         `NOTIF_I3C_HJ` notification; otherwise `nullptr`.
   */
  COSMICSDK_API const I3cHotJoinNotification* i3cHotJoin() const noexcept;

  /**
   * @brief Parses this notification as I3C In-Band Interrupt (IBI) data.
   * @note C++ only. Not available in the C API.
   *
   * This method validates @p type and payload length before decoding.
   *
   * @return Pointer to parsed @ref I3cIbiNotification when this is a valid
   *         `NOTIF_I3C_IBI` notification; otherwise `nullptr`.
   */
  COSMICSDK_API const I3cIbiNotification* i3cIbi() const noexcept;

  /**
   * @brief Parses this notification as GPIO interrupt data.
   * @note C++ only. Not available in the C API.
   *
   * This method validates @p type and payload length before decoding.
   *
   * @return Pointer to parsed @ref GpioInterruptNotification when this is a
   *         valid `NOTIF_GPIO` notification; otherwise `nullptr`.
   */
  COSMICSDK_API const GpioInterruptNotification* gpio() const noexcept;

  /**
   * @brief Parses this notification as UART RX data.
   * @note C++ only. Not available in the C API.
   *
   * This method validates @p type and payload length before decoding.
   *
   * @return Pointer to parsed @ref UartRxNotification when this is a valid
   *         `NOTIF_UART` notification; otherwise `nullptr`.
   */
  COSMICSDK_API const UartRxNotification* uartRx() const noexcept;

private:
  mutable I3cHotJoinNotification i3cHjCache{};
  mutable I3cIbiNotification i3cIbiCache{};
  mutable GpioInterruptNotification gpioCache{};
  mutable UartRxNotification uartRxCache{};
#endif

} Notification;
