#define USE_DESKTOP 1

#include "mmdvm-display/mmdvm-display.ino"

#include <csignal>
#include <exception>

static void desktopSignalHandler(int sig) {
  desktopTrace("[DESKTOP][FATAL] signal %d caught. Emergency exit without SDL shutdown.\n", sig);
#if defined(_WIN32)
  ::ExitProcess((UINT)(128 + sig));
#else
  std::_Exit(128 + sig);
#endif
}

int main(int argc, char** argv) {
  (void)argc;
  (void)argv;

  desktopInitLog();
  desktopTrace("[DESKTOP] process started.\n");
#if defined(_WIN32)
  desktopTrace("[DESKTOP] platform: Windows/MinGW.\n");
#else
  desktopTrace("[DESKTOP] platform: Linux/Unix.\n");
#endif

  std::signal(SIGSEGV, desktopSignalHandler);
  std::signal(SIGABRT, desktopSignalHandler);
  std::signal(SIGFPE,  desktopSignalHandler);
  std::signal(SIGILL,  desktopSignalHandler);
#if !defined(_WIN32)
  std::signal(SIGTERM, desktopSignalHandler);
  std::signal(SIGINT,  desktopSignalHandler);
#endif

  try {
    desktopTrace("[DESKTOP] calling setup().\n");
    setup();
    desktopTrace("[DESKTOP] setup() complete; entering desktop main loop. Close the SDL window to exit.\n");
    unsigned long lastHeartbeat = millis();
    unsigned long lastSafeDraw = millis();
    unsigned long lastSafeLog = millis();
    unsigned long lastLoopTrace = 0;
    unsigned int safeDrawCount = 0;
    bool usedSafeDesktopLoop = false;
    desktopTrace("[DESKTOP] main: timers initialized.\n");
#if defined(_WIN32)
    if (!desktopSdlEventPollingEnabled()) {
      desktopTrace("[DESKTOP] main: SDL event polling disabled on Windows; native Win32 mouse pump is active. Close the window or press Ctrl+C to exit.\n");
    } else {
      desktopTrace("[DESKTOP] main: SDL event polling enabled by MMDVM_DESKTOP_SDL_EVENTS=1.\n");
    }
#endif
    desktopTrace("[DESKTOP] main: entering while loop.\n");

#if defined(_WIN32) && DISPLAY_BACKEND_IS_DESKTOP
    const char* holdEnv = std::getenv("MMDVM_DESKTOP_HOLD_LOOP");
    const bool holdLoop = holdEnv && std::strcmp(holdEnv, "1") == 0;
    if (holdLoop) {
      desktopTrace("[DESKTOP] main: Windows hold loop active by MMDVM_DESKTOP_HOLD_LOOP=1.\n");
      desktopTrace("[DESKTOP] main: press Ctrl+C in this terminal to exit.\n");
      unsigned long tick = 0;
      for (;;) {
        if (!desktopWin32PumpMessagesNoSDL()) {
          desktopTrace("[DESKTOP] main: native window close requested. Exiting hold loop.\n");
          break;
        }
        ++tick;
        desktopTrace("[DESKTOP] heartbeat: running.\n");
        if ((tick % 5UL) == 0UL) desktopTrace("[DESKTOP] main: desktop display hold mode is idle.\n");
        for (int i = 0; i < 10; ++i) {
          if (!desktopWin32PumpMessagesNoSDL()) break;
          desktopSleepMs(100);
        }
      }
      desktopTrace("[DESKTOP] main: hold loop ended; exiting normally.\n");
      desktopShutdown();
      return 0;
    }
    desktopTrace("[DESKTOP] main: desktop UI loop enabled; mouse maps to touch. Network polling is enabled by default; set MMDVM_DESKTOP_NETWORK=0 for UI-only mode.\n");
#endif

    while (desktopRunning()) {
#if DISPLAY_BACKEND_IS_DESKTOP
      desktopPollEventsOnly();
#endif
#if DISPLAY_BACKEND_IS_DESKTOP
      if (setupRequired || apModeActive) {
        usedSafeDesktopLoop = true;
        desktopPollEventsOnly();

        if (uiDirty || footerDirty || headerClockDirty || scrollingTextDirty) {
          lastSafeDraw = millis();
          if (safeDrawCount < 3) desktopTrace("[DESKTOP] main: safe redraw requested.\n");
          ++safeDrawCount;
          desktopTrace("[DESKTOP] main: redraw enter.\n");
          drawDesktopBootReadyPage();
          desktopTrace("[DESKTOP] main: redraw leave.\n");
          uiDirty = false;
          footerDirty = false;
          headerClockDirty = false;
          scrollingTextDirty = false;
        }
        if (millis() - lastSafeLog >= 5000UL) {
          lastSafeLog = millis();
          desktopTrace("[DESKTOP] main: safe setup/AP loop active.\n");
        }
        if (millis() - lastHeartbeat >= 1000UL) {
          lastHeartbeat = millis();
          desktopTrace("[DESKTOP] heartbeat: running.\n");
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        continue;
      }
#endif
      if (usedSafeDesktopLoop || millis() - lastLoopTrace >= 1000UL) {
        usedSafeDesktopLoop = false;
        lastLoopTrace = millis();
        desktopTrace("[DESKTOP] main: calling Arduino loop().\n");
      }
      static bool firstFirmwareLoopReturned = false;
      loop();
      if (!firstFirmwareLoopReturned) {
        firstFirmwareLoopReturned = true;
        desktopTrace("[DESKTOP] main: first loop() returned.\n");
      }
      if (millis() - lastHeartbeat >= 1000UL) {
        lastHeartbeat = millis();
        desktopTrace("[DESKTOP] heartbeat: running.\n");
      }
      desktopSleepMs(10);
    }
    desktopTrace("[DESKTOP] window closed; exiting normally.\n");
    desktopShutdown();
    return 0;
  } catch (const std::exception& e) {
    desktopTrace("[DESKTOP][FATAL] exception: %s\n", e.what());
  } catch (...) {
    desktopTrace("[DESKTOP][FATAL] unknown exception.\n");
  }
  desktopShutdown();
  return 1;
}
