/**
 * @file qdx_port.h
 * @brief Hardware/OS Abstraction Layer (HAL) for QDX Network Stack
 *
 * Provides platform-independent interfaces for network socket operations,
 * timing, mutexes, and threading. Users must implement these functions
 * based on their specific MCU OS (e.g., FreeRTOS, LwIP, RT-Thread).
 */

#ifndef QDX_PORT_H
#define QDX_PORT_H

#include <stdint.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ============================================================
 * Multi-Level Debug Print System
 *
 * Verbosity levels (set DBG_LEVEL to control output volume):
 *   0 = NONE    — all debug prints disabled
 *   1 = ERR     — errors only
 *   2 = BRIEF   — + server config / network events  (recommended)
 *   3 = NORMAL  — + trigger / data / init events     (default)
 *   4 = VERBOSE — + heartbeat / detailed internals
 *
 * Category macros — each prints when DBG_LEVEL >= its threshold:
 *   DBG_ERR   (>=1)  Errors, HardFault, CRC fail, bad frames
 *   DBG_CFG   (>=2)  Server-received config (Config2D/1D/Common, DevID, ACK, DetResult)
 *   DBG_NET   (>=2)  TCP connect/disconnect, PHY change, socket events
 *   DBG_TRIG  (>=3)  Trigger events (ext/int), burst start/complete
 *   DBG_DATA  (>=3)  Frame send results (2D/1D/TEMP_REQ)
 *   DBG_INIT  (>=3)  Boot-time init messages (sensor, DVP, WCHNET)
 *   DBG_HB    (>=4)  Heartbeat prints (high-frequency, debug only)
 * ============================================================ */
#define DBG_LEVEL_NONE      0
#define DBG_LEVEL_ERR       1
#define DBG_LEVEL_BRIEF     2
#define DBG_LEVEL_NORMAL    3
#define DBG_LEVEL_VERBOSE   4

/* >>> Change this single value to control output volume <<< */
#define DBG_LEVEL           DBG_LEVEL_NORMAL

#define DBG_PRINT_(threshold, tag, fmt, ...) \
    do { if (DBG_LEVEL >= (threshold)) printf(tag fmt, ##__VA_ARGS__); } while(0)

#define DBG_ERR(fmt, ...)   DBG_PRINT_(DBG_LEVEL_ERR,     "[ERR]  ", fmt, ##__VA_ARGS__)
#define DBG_CFG(fmt, ...)   DBG_PRINT_(DBG_LEVEL_BRIEF,   "[CFG]  ", fmt, ##__VA_ARGS__)
#define DBG_NET(fmt, ...)   DBG_PRINT_(DBG_LEVEL_BRIEF,   "[NET]  ", fmt, ##__VA_ARGS__)
#define DBG_TRIG(fmt, ...)  DBG_PRINT_(DBG_LEVEL_NORMAL,  "[TRIG] ", fmt, ##__VA_ARGS__)
#define DBG_DATA(fmt, ...)  DBG_PRINT_(DBG_LEVEL_NORMAL,  "[DATA] ", fmt, ##__VA_ARGS__)
#define DBG_INIT(fmt, ...)  DBG_PRINT_(DBG_LEVEL_NORMAL,  "[INIT] ", fmt, ##__VA_ARGS__)
#define DBG_HB(fmt, ...)    DBG_PRINT_(DBG_LEVEL_VERBOSE, "[HB]   ", fmt, ##__VA_ARGS__)

/* Legacy compatibility aliases — avoid using in new code */
#define DBG_PORT(fmt, ...)  DBG_INIT(fmt, ##__VA_ARGS__)
#define DBG_LOGIC(fmt, ...) DBG_CFG(fmt, ##__VA_ARGS__)
#define DBG_APP(fmt, ...)   DBG_DATA(fmt, ##__VA_ARGS__)

/* ============================================================
 * Time & Delay
 * ============================================================ */

/**
 * @brief Get absolute system uptime/ticks in milliseconds.
 * @return Milliseconds since system boot.
 */
uint32_t qdx_port_get_tick_ms(void);

/**
 * @brief Blocking delay in milliseconds.
 * @param ms Delay time
 */
void qdx_port_delay_ms(uint32_t ms);

/* ============================================================
 * Network (TCP Socket)
 * ============================================================ */

/* Opaque handle for sockets dependent on underlying IP stack */
typedef void *qdx_socket_t;

/**
 * @brief Create and connect a TCP socket to a remote host.
 * @param ip Str IP address of the server (e.g., "192.168.1.10")
 * @param port Remote port
 * @return Valid socket handle on success, or NULL on failure.
 */
qdx_socket_t qdx_port_tcp_connect(const char *ip, uint16_t port);

/**
 * @brief Close a TCP socket.
 * @param sock Socket handle
 */
void qdx_port_tcp_close(qdx_socket_t sock);

/**
 * @brief Send data over TCP socket.
 * @param sock Socket handle
 * @param data Data buffer to send
 * @param len Length of data in bytes
 * @return Number of bytes sent, or < 0 for error.
 */
int32_t qdx_port_tcp_send(qdx_socket_t sock, const uint8_t *data, uint32_t len);

/**
 * @brief Receive data from TCP socket (Non-blocking or specific timeout).
 * @param sock Socket handle
 * @param buf Buffer to store received data
 * @param max_len Maximum buffer size
 * @return Number of bytes received. Return 0 if timeout/empty. Return < 0 for
 * connection closed/error.
 */
int32_t qdx_port_tcp_recv(qdx_socket_t sock, uint8_t *buf, uint32_t max_len);

/* ============================================================
 * Mutex & Threading
 * ============================================================ */

/* Opaque handle for mutex */
typedef void *qdx_mutex_t;

/**
 * @brief Create a recursive or standard mutex.
 * @return Mutex handle, or NULL on failure.
 */
qdx_mutex_t qdx_port_mutex_create(void);

/**
 * @brief Lock a mutex.
 * @param mutex Mutex handle
 */
void qdx_port_mutex_lock(qdx_mutex_t mutex);

/**
 * @brief Unlock a mutex.
 * @param mutex Mutex handle
 */
void qdx_port_mutex_unlock(qdx_mutex_t mutex);

/**
 * @brief Delete a mutex.
 * @param mutex Mutex handle
 */
void qdx_port_mutex_delete(qdx_mutex_t mutex);

/* Thread entry callback definition */
typedef void (*qdx_thread_entry_t)(void *arg);

/**
 * @brief Create a background thread/task.
 * @param name Task name
 * @param entry Task entry function
 * @param arg Task argument
 * @param stack_size Requested stack size in bytes
 * @param priority Task priority
 * @return 0 on success, < 0 on failure.
 */
int8_t qdx_port_thread_create(const char *name, qdx_thread_entry_t entry,
                              void *arg, uint32_t stack_size, uint8_t priority);

#ifdef __cplusplus
}
#endif

#endif /* QDX_PORT_H */
