/**
 * @file qdx_port_template.c
 * @brief Template Implementation of the HAL Port for QDX Network Stack
 *
 * Instructions:
 * 1. Rename this file to qdx_port.c in your MCU project.
 * 2. Implement these functions using your specific OS/Network APIs
 *    (e.g., LwIP, FreeRTOS, RT-Thread, CMSIS-OS).
 * 3. Ensure qdx_port_tcp_recv is non-blocking or uses a short timeout,
 *    so the background thread can periodically check connection status.
 */

#include "qdx_port.h"
#include <stddef.h> /* For NULL */
/* Include your system headers here
 * #include "FreeRTOS.h"
 * #include "task.h"
 * #include "lwip/sockets.h"
 * #include "lwip/sys.h"
 */

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

uint32_t qdx_port_get_tick_ms(void) {
  /* TODO: Return current system uptime in milliseconds.
   * Example (FreeRTOS): return (uint32_t)(xTaskGetTickCount() *
   * portTICK_PERIOD_MS); Example (HAL): return HAL_GetTick();
   */
  return 0;
}

void qdx_port_delay_ms(uint32_t ms) {
  /* TODO: Block current thread for ms milliseconds.
   * Example (FreeRTOS): vTaskDelay(pdMS_TO_TICKS(ms));
   * Example (HAL): HAL_Delay(ms);
   */
}

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

qdx_socket_t qdx_port_tcp_connect(const char *ip, uint16_t port) {
  /* TODO: Create socket and connect to IP:PORT.
   * Example (LwIP/BSD Sockets):
   *   int sock = socket(AF_INET, SOCK_STREAM, 0);
   *   if (sock < 0) return NULL;
   *   struct sockaddr_in dest_addr;
   *   dest_addr.sin_addr.s_addr = inet_addr(ip);
   *   dest_addr.sin_family = AF_INET;
   *   dest_addr.sin_port = htons(port);
   *   if (connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) == 0)
   * {
   *       // Optional: Set receive timeout
   *       return (qdx_socket_t)(intptr_t)sock;
   *   }
   *   close(sock);
   */
  return NULL;
}

void qdx_port_tcp_close(qdx_socket_t sock) {
  /* TODO: Close the socket gracefully.
   * Example:
   *   if (sock) {
   *       close((int)(intptr_t)sock);
   *   }
   */
}

int32_t qdx_port_tcp_send(qdx_socket_t sock, const uint8_t *data,
                          uint32_t len) {
  /* TODO: Send data through the socket.
   * Example:
   *   if (!sock) return -1;
   *   return send((int)(intptr_t)sock, data, len, 0);
   */
  return -1;
}

int32_t qdx_port_tcp_recv(qdx_socket_t sock, uint8_t *buf, uint32_t max_len) {
  /* TODO: Receive data from the socket.
   * Should return actual bytes read. If no bytes are available (timeout),
   * return 0. If socket is closed or an error occurs, return < 0. Example: if
   * (!sock) return -1;
   *   // Assume socket was set with SO_RCVTIMEO to prevent hanging forever
   *   int bytes = recv((int)(intptr_t)sock, buf, max_len, 0);
   *   if (bytes < 0) {
   *       if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; // Timeout
   *       return -1; // Actual error
   *   }
   *   return bytes; // Includes bytes == 0 (graceful close) -> might want to
   * map to -1
   */
  return -1;
}

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

qdx_mutex_t qdx_port_mutex_create(void) {
  /* TODO: Create and return a mutex handle.
   * Example (FreeRTOS):
   *   SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
   *   return (qdx_mutex_t)mutex;
   */
  return NULL;
}

void qdx_port_mutex_lock(qdx_mutex_t mutex) {
  /* TODO: Lock the given mutex.
   * Example (FreeRTOS):
   *   if (mutex) xSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY);
   */
}

void qdx_port_mutex_unlock(qdx_mutex_t mutex) {
  /* TODO: Unlock the given mutex.
   * Example (FreeRTOS):
   *   if (mutex) xSemaphoreGive((SemaphoreHandle_t)mutex);
   */
}

void qdx_port_mutex_delete(qdx_mutex_t mutex) {
  /* TODO: Delete the given mutex.
   * Example (FreeRTOS):
   *   if (mutex) vSemaphoreDelete((SemaphoreHandle_t)mutex);
   */
}

int8_t qdx_port_thread_create(const char *name, qdx_thread_entry_t entry,
                              void *arg, uint32_t stack_size,
                              uint8_t priority) {
  /* TODO: Create a background thread/task to run the entry function.
   * Example (FreeRTOS):
   *   BaseType_t res = xTaskCreate(entry, name, stack_size /
   * sizeof(StackType_t), arg, priority, NULL); return (res == pdPASS) ? 0 : -1;
   */
  return -1;
}
