#pragma once

#include "../WidgetConfig.hpp"
#include "lvgl.h"
#include <ctime>

class WidgetManager;

class Widget {
public:
    explicit Widget(const WidgetConfig& config);
    virtual ~Widget();

    // Delete copy/move
    Widget(const Widget&) = delete;
    Widget& operator=(const Widget&) = delete;

    // Destroy LVGL object
    void destroy();

    // Access to LVGL object
    lv_obj_t* getLvglObject() const { return obj_; }
    lv_obj_t* getObj() const { return obj_; } // Alias
    void clearLvglObject() { obj_ = nullptr; }

    // Widget ID
    uint8_t getId() const { return config_.id; }

    // KNX group address for read binding
    uint16_t getKnxAddress() const { return config_.knxAddress; }
    uint16_t getKnxAddress2() const { return config_.knxAddress2; }
    uint16_t getKnxAddress3() const { return config_.knxAddress3; }

    // TextSource for KNX callback filtering
    TextSource getTextSource() const { return config_.textSource; }
    TextSource getTextSource2() const { return config_.textSource2; }
    TextSource getTextSource3() const { return config_.textSource3; }

    // Widget type
    WidgetType getType() const { return config_.type; }

    // Config access (for button action handling)
    const WidgetConfig& getConfig() const { return config_; }

    // Create LVGL widget on parent - must be implemented by subclasses
    virtual lv_obj_t* create(lv_obj_t* parent) = 0;

    // Apply styling after create() - can be overridden
    virtual void applyStyle();

    // KNX callbacks - default implementations do nothing
    virtual void onKnxValue(float value);
    virtual void onKnxValue2(float value);  // For secondary address (left)
    virtual void onKnxValue3(float value);  // For tertiary address (right)
    virtual void onKnxSwitch(bool value);
    virtual void onKnxText(const char* text);
    virtual void onKnxTime(const struct tm& value, TextSource source);
    virtual void onHistoryUpdate();

    // Condition evaluation - returns true if style was changed
    virtual bool evaluateConditions(float primaryValue, float secondaryValue, float tertiaryValue);

    // Get cached values for condition evaluation
    float getCachedPrimaryValue() const { return cachedPrimaryValue_; }
    float getCachedSecondaryValue() const { return cachedSecondaryValue_; }
    float getCachedTertiaryValue() const { return cachedTertiaryValue_; }

protected:
    // Common style helper functions
    void applyCommonStyle();
    void applyShadowStyle();
    void applyConditionStyle(const ConditionStyle& style);
    static const lv_font_t* getFontBySize(uint8_t sizeIndex);

    // Night mode color transformation
    bool shouldTransformColors() const;
    Color themeColor(const Color& c) const;

    const WidgetConfig& config_;
    lv_obj_t* obj_ = nullptr;

    // Cached values for condition evaluation
    float cachedPrimaryValue_ = 0.0f;
    float cachedSecondaryValue_ = 0.0f;
    float cachedTertiaryValue_ = 0.0f;
    bool hasCachedPrimary_ = false;
    bool hasCachedSecondary_ = false;
    bool hasCachedTertiary_ = false;

    // Current applied condition (for detecting changes)
    uint32_t currentConditionIcon_ = 0;
};
