#include "uiEventHandler.h"

#include "../mainFrame.h"
#include "core/context.h"
#include "misc/tools.h"

#include <iostream>
#include <sdi_toolBox/desktop/utils/uuid.h>

using namespace std;
using namespace gui;
//--------------------------------------------------------------
/* Constructor */
UiEventHandler::UiEventHandler(MainFrame &owner, core::Context &ctx)
  : Node(ctx.eventBus)
  , m_owner(owner)
  , m_ctx(ctx)
{
  // Start the event handling thread
  startEventThread();

  // Subscribe to relevant message types
  subscribe(eventBus::NavBridge_sendMessage::MESSAGE_ID);
}
//--------------------------------------------------------------
/* Post a message to the UI with a specific topic and payload */
void UiEventHandler::postEventMessage(const std::string &topic, const json &payload) const
{
  // Construct the message as a JSON object
  const auto id        = sdi_toolBox::desktop::utils::uuid::v7();
  const auto timestamp = tools::make_iso8601_utc_timestamp();

  const json message = {
    { "kind", "eventMessage" },
    { "id", id },
    { "timestamp", timestamp },
    { "topic", topic },
    { "payload", payload }
  };

  processOutgoingMessage(message);
}
//--------------------------------------------------------------
/* Post a response message to the UI with a specific topic, request ID, status, and payload */
void UiEventHandler::postResponseMessage(const std::string &topic, const std::string &requestId, bool isOk, const json &payload) const
{
  // Construct the message as a JSON object
  const auto id        = sdi_toolBox::desktop::utils::uuid::v7();
  const auto timestamp = tools::make_iso8601_utc_timestamp();

  const json message = {
    { "kind", "responseMessage" },
    { "id", id },
    { "requestId", requestId },
    { "timestamp", timestamp },
    { "topic", topic },
    { "ok", isOk },
    { "payload", payload }
  };

  processOutgoingMessage(message);
}
//--------------------------------------------------------------
/* Default destructor */
UiEventHandler::~UiEventHandler()
{
  // Stop the event handling thread
  stopEventThread();
}
//--------------------------------------------------------------
/* Process incoming messages from the UI */
void UiEventHandler::processIncomingMessage(const json &message)
{
  // For debugging: print the received message
  cout << "Received message from WebView:\n"
       << message.dump(2) << "\n"
       << endl;
}
//--------------------------------------------------------------
/* Process outgoing messages to the UI */
void UiEventHandler::processOutgoingMessage(const json &message) const
{
  // Sanity check: ensure the message is correctly formatted and
  // contains the expected fields

  cout << "Sending message to WebView:\n"
       << message.dump(2) << "\n"
       << endl;

  m_owner.CallAfter([this, message]()
                    { m_owner.m_browser->RunScriptAsync("window.kwaUiBridge.receiveFromBackend(" + message.dump() + ");"); });
}
//--------------------------------------------------------------
/* Start the event handling thread */
void UiEventHandler::startEventThread()
{
  if (!m_thread.joinable())
  {
    m_thread = std::jthread([&](const std::stop_token &token)
                            { processEvents(token); });
  }
}
//--------------------------------------------------------------
/* Stop the event handling thread */
void UiEventHandler::stopEventThread()
{
  if (m_thread.joinable())
  {
    m_thread.request_stop();
    messageNotify();     // Notify the thread to wake up if it's waiting for
                         // messages
    m_thread.join();
  }
}
//--------------------------------------------------------------
/* Event processing loop */
void UiEventHandler::processEvents(const std::stop_token &stopToken)
{
  while (!stopToken.stop_requested())
  {
    // Wait for a message to be posted to the bus and received by the node
    syncWaitForMessage();

    // Process all messages in the queue
    while (getMessageCount() > 0)
    {
      // Get the front message from the queue
      const auto message = popMessage();

      const auto sendMessage = dynamic_pointer_cast<eventBus::NavBridge_sendMessage>(message);
      if (sendMessage)
      {
      }
      break;
    }
  }
}
//--------------------------------------------------------------
