#include <DHCP/dhcp.h>

#include "ch32v003fun.h"
#include "debug.h"
#include "gpio.h"
#include "socket.h"
#include "spi_dma.h"
#include "systick.h"
#include "timer.h"
#include "uart.h"
#include "w5500.h"

void init_system(void) {
  SystemInit();

  init_gpio();
  init_uart(UART_BRR_APB1);
  init_spidma();
}

// cb fn for when a message is received
void message_arrived(MessageData* md) {
  if (md == NULL || md->message == NULL) {
    DEBUG_PRINT("Error: MessageData is NULL.\n");
    return;
  }

  MQTTMessage* message = md->message;
  DEBUG_PRINT("MQTT Message Arrived:\n");
  DEBUG_PRINT("QoS: %d\n", message->qos);
  DEBUG_PRINT("Retained: %d\n", message->retained);
  DEBUG_PRINT("Duplicate: %d\n", message->dup);
  DEBUG_PRINT("Message ID: %u\n", message->id);
  DEBUG_PRINT("Payload Length: %u\n", (unsigned int)message->payloadlen);

  if (message->payload != NULL && message->payloadlen > 0) {
    DEBUG_PRINT("Payload: ");
    for (unsigned int i = 0; i < (unsigned int)message->payloadlen; ++i) {
      putchar(((unsigned char*)message->payload)[i]);
    }
    DEBUG_PRINT("\n");
  } else {
    DEBUG_PRINT("Payload: <No data>\n");
  }
}

int main(void) {
  init_system();
  configure_network();

  // TODO: enabling any kind of SysTick IRQ literally causes the socket to hang forever
  // with 1ms interval the hang is on DHCP_ACK, on check_DHCP_leasedIP -> sendto() ARP req
  // with 1s it happens somewhere on DNS req
  init_systick();
  tim2_init();

  // systick irq enable here would complete the DHCP configuration and hang on DNS..
  // init_systick();

  configure_dhcp();
  resolve_domain_name("example.com");

  Network network;
  ch32_mqtt_options_t opts = {CLIENT_ID, "", "", QOS0};

  // Set up MQTT client
  MQTTClient client = setup_mqtt_client(&network, &opts);
  subscribe_to_topic(&client, SUB_TOPIC, QOS0, message_arrived);

  // Publish a message
  publish_message(&client, "hi", PUB_TOPIC);

  while (1) {
    // if ((millis() - dhcp_last_invocation) >= DHCP_INTERVAL) {
    //   dhcp_last_invocation = millis();
    //   DHCP_run();
    // }
    MQTTYield(&client, 1000);  // keepalive
  }

  MQTTDisconnect(&client);
  close(TCP_SOCKET);

  return 0;
}
