#pragma once

#include "NodeDB.h"
#include "graphics/EmoteRenderer.h"
#include "graphics/Screen.h"
#include "graphics/emotes.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include <string>

#define HOURS_IN_MONTH 730

// Forward declarations for status types
namespace meshtastic
{
class PowerStatus;
class NodeStatus;
class GPSStatus;
} // namespace meshtastic

namespace graphics
{

/// Forward declarations
class Screen;

/**
 * @brief UI utility drawing functions
 *
 * Contains utility functions for drawing common UI elements, overlays,
 * battery indicators, and other shared graphical components.
 */
class UIRenderer
{
  public:
    // Common UI elements
    static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::NodeStatus *nodeStatus,
                          int node_offset = 0, bool show_total = true, const char *additional_words = "", bool center = false);

    // GPS status functions
    static void drawGps(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus, bool center = false);
    static void drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus,
                                   const char *mode = "line1");
    static void drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);

    // Overlay and special screens
    static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *text);

    // Navigation bar overlay
    static void drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *state);
    // Compact panels: called when the screen turns back on, so the intro splash replays even
    // though drawNavigationBar itself never ran while the screen (and its OSThread) was off.
    static void notifyScreenWoke();

    static void drawFavoriteNode(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
    // Compact panels: toggle between compass+distance view and status/telemetry view
    static void scrollFavoriteDown();
    static void scrollFavoriteUp();

    static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

    static void drawBootIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

    // Icon and screen drawing functions
    static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

    // Compass and location screen
    static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
    // Compact panels: toggle between compass view and coordinates+elevation view
    static void scrollPositionDown();
    static void scrollPositionUp();

    static NodeNum currentFavoriteNodeNum;
    static std::vector<meshtastic_NodeInfoLite *> favoritedNodes;
    static void rebuildFavoritedNodes();

// OEM screens
#ifdef USERPREFS_OEM_TEXT
    static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
    static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#endif

#ifdef USE_EINK
    /// Used on eink displays while in deep sleep
    static void drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

    /// Used on eink displays when screen updates are paused
    static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
#endif

    static std::string drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds);
    static int formatDateTime(char *buffer, size_t bufferSize, uint32_t rtc_sec, OLEDDisplay *display, bool showTime);

    // Shared BaseUI emote helpers.
    static int measureStringWithEmotes(OLEDDisplay *display, const char *line, int emoteSpacing = 1);
    static inline int measureStringWithEmotes(OLEDDisplay *display, const std::string &line, int emoteSpacing = 1)
    {
        return measureStringWithEmotes(display, line.c_str(), emoteSpacing);
    }
    static size_t truncateStringWithEmotes(OLEDDisplay *display, const char *line, char *out, size_t outSize, int maxWidth,
                                           const char *ellipsis = "...", int emoteSpacing = 1);
    static inline std::string truncateStringWithEmotes(OLEDDisplay *display, const std::string &line, int maxWidth,
                                                       const std::string &ellipsis = "...", int emoteSpacing = 1)
    {
        return graphics::EmoteRenderer::truncateToWidth(display, line, maxWidth, ellipsis, graphics::emotes, graphics::numEmotes,
                                                        emoteSpacing);
    }
    static void drawStringWithEmotes(OLEDDisplay *display, int x, int y, const char *line, int fontHeight, int emoteSpacing = 1,
                                     bool fauxBold = true);
    static inline void drawStringWithEmotes(OLEDDisplay *display, int x, int y, const std::string &line, int fontHeight,
                                            int emoteSpacing = 1, bool fauxBold = true)
    {
        drawStringWithEmotes(display, x, y, line.c_str(), fontHeight, emoteSpacing, fauxBold);
    }
}; // namespace UIRenderer

} // namespace graphics
