#pragma once

#include <cstdint>
#include <cstddef>
#include <cstring>

// Maximum number of widgets
static constexpr size_t MAX_WIDGETS = 32;
static constexpr size_t MAX_SCREENS = 8;
static constexpr size_t MAX_TEXT_LEN = 32;
static constexpr size_t MAX_SCREEN_NAME_LEN = 24;

enum class WidgetType : uint8_t {
    LABEL = 0,
    BUTTON = 1,
    LED = 2,
    ICON = 3,
    TABVIEW = 4,
    TABPAGE = 5,
    POWERFLOW = 6,
    POWERNODE = 7,
    POWERLINK = 8,
};

enum class IconPosition : uint8_t {
    LEFT = 0,
    RIGHT = 1,
    TOP = 2,
    BOTTOM = 3,
};

enum class ScreenMode : uint8_t {
    FULLSCREEN = 0,
    MODAL = 1,
};

enum class ButtonAction : uint8_t {
    KNX = 0,
    JUMP = 1,
    BACK = 2,
};

// Text source: static text or KNX group address
enum class TextSource : uint8_t {
    STATIC = 0,      // Static text
    KNX_DPT_TEMP = 1,    // KNX Temperature (DPT 9.001)
    KNX_DPT_SWITCH = 2,  // KNX Switch (DPT 1.001)
    KNX_DPT_PERCENT = 3, // KNX Percent (DPT 5.001)
    KNX_DPT_TEXT = 4,    // KNX Text (DPT 16.000)
};

enum class TextAlign : uint8_t {
    LEFT = 0,
    CENTER = 1,
    RIGHT = 2,
};

// Color as RGB888
struct Color {
    uint8_t r, g, b;

    uint32_t toLvColor() const {
        return (r << 16) | (g << 8) | b;
    }

    static Color fromHex(uint32_t hex) {
        return {
            .r = static_cast<uint8_t>((hex >> 16) & 0xFF),
            .g = static_cast<uint8_t>((hex >> 8) & 0xFF),
            .b = static_cast<uint8_t>(hex & 0xFF)
        };
    }
};

// Shadow configuration
struct ShadowConfig {
    int8_t offsetX;
    int8_t offsetY;
    uint8_t blur;
    uint8_t spread;
    Color color;
    bool enabled;
};

// Widget configuration
struct WidgetConfig {
    // Basic properties
    uint8_t id;              // Unique ID (0-255)
    WidgetType type;
    int16_t x, y;
    int16_t width, height;
    bool visible;

    // Text properties
    TextSource textSource;
    char text[MAX_TEXT_LEN]; // Static text or format string
    uint16_t knxAddress;     // KNX group address (if textSource != STATIC)
    uint8_t fontSize;        // Font size index (0=14, 1=18, 2=22, 3=28, 4=36, 5=48)
    uint8_t textAlign;       // TextAlign: 0=left, 1=center, 2=right
    bool isContainer;        // For buttons: use as container (no internal label/icon)

    // Colors
    Color textColor;
    Color bgColor;
    uint8_t bgOpacity;       // 0-255
    uint8_t borderRadius;

    // Shadow
    ShadowConfig shadow;

    // Button specific
    bool isToggle;           // For buttons: toggle mode
    uint16_t knxAddressWrite; // KNX address to write on click
    ButtonAction action;     // Button action (KNX, Jump, Back)
    uint8_t targetScreen;    // Target screen ID for jump

    // Icon properties (for Label, Button, Icon widgets)
    uint32_t iconCodepoint;  // Unicode codepoint (0 = no icon)
    uint8_t iconPosition;    // IconPosition: 0=left, 1=right, 2=top, 3=bottom
    uint8_t iconSize;        // Font size index (0-5), same as fontSize
    int8_t iconGap;          // Gap between icon and text (px)

    // Hierarchy
    int8_t parentId;         // ID of parent widget (-1 = root/screen)

    // Serialization size (fixed for NVS storage)
    static constexpr size_t SERIALIZED_SIZE = 78;

    void serialize(uint8_t* buf) const;
    void deserialize(const uint8_t* buf);

    // Create default label
    static WidgetConfig createLabel(uint8_t id, int16_t x, int16_t y, const char* text);

    // Create KNX-bound label
    static WidgetConfig createKnxLabel(uint8_t id, int16_t x, int16_t y,
                                        TextSource source, uint16_t knxAddr, const char* format);

    // Create button
    static WidgetConfig createButton(uint8_t id, int16_t x, int16_t y,
                                     const char* text, uint16_t knxAddrWrite, bool toggle);
};

// Screen configuration (holds all widgets)
struct ScreenConfig {
    uint8_t id;
    char name[MAX_SCREEN_NAME_LEN];
    ScreenMode mode;
    Color backgroundColor;
    uint8_t widgetCount;
    WidgetConfig widgets[MAX_WIDGETS];

    // Modal-specific properties (only used when mode == MODAL)
    int16_t modalX;          // Modal position X (0 = centered)
    int16_t modalY;          // Modal position Y (0 = centered)
    int16_t modalWidth;      // Modal width (0 = auto from content)
    int16_t modalHeight;     // Modal height (0 = auto from content)
    uint8_t modalBorderRadius;
    bool modalDimBackground; // Dim the background behind modal

    void clear(uint8_t newId = 0, const char* newName = nullptr);
    int addWidget(const WidgetConfig& widget);  // Returns widget ID or -1
    bool removeWidget(uint8_t id);
    WidgetConfig* findWidget(uint8_t id);
    const WidgetConfig* findWidget(uint8_t id) const;
};

struct GuiConfig {
    uint8_t screenCount;
    ScreenConfig screens[MAX_SCREENS];
    uint8_t startScreenId;
    bool standbyEnabled;
    uint8_t standbyScreenId;
    uint16_t standbyMinutes;

    void clear();
    ScreenConfig* findScreen(uint8_t id);
    const ScreenConfig* findScreen(uint8_t id) const;
};
