#include "IconWidget.hpp"
#include "../Fonts.hpp"
#include "esp_log.h"

static const char* TAG = "IconWidget";

IconWidget::IconWidget(const WidgetConfig& config)
    : Widget(config)
    , iconLabel_(nullptr)
{
}

int IconWidget::encodeUtf8(uint32_t codepoint, char* buf) {
    if (codepoint < 0x80) {
        buf[0] = static_cast<char>(codepoint);
        buf[1] = '\0';
        return 1;
    } else if (codepoint < 0x800) {
        buf[0] = static_cast<char>(0xC0 | (codepoint >> 6));
        buf[1] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[2] = '\0';
        return 2;
    } else if (codepoint < 0x10000) {
        buf[0] = static_cast<char>(0xE0 | (codepoint >> 12));
        buf[1] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
        buf[2] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[3] = '\0';
        return 3;
    } else if (codepoint < 0x110000) {
        buf[0] = static_cast<char>(0xF0 | (codepoint >> 18));
        buf[1] = static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F));
        buf[2] = static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
        buf[3] = static_cast<char>(0x80 | (codepoint & 0x3F));
        buf[4] = '\0';
        return 4;
    }
    buf[0] = '\0';
    return 0;
}

lv_obj_t* IconWidget::create(lv_obj_t* parent) {
    // Create container for the icon
    obj_ = lv_obj_create(parent);
    if (obj_ == nullptr) {
        ESP_LOGE(TAG, "Failed to create icon widget object");
        return nullptr;
    }
    lv_obj_remove_style_all(obj_);
    lv_obj_set_pos(obj_, config_.x, config_.y);
    lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 48,
                          config_.height > 0 ? config_.height : 48);

    // Create icon label
    iconLabel_ = lv_label_create(obj_);

    if (config_.iconCodepoint > 0) {
        char iconText[5];
        encodeUtf8(config_.iconCodepoint, iconText);
        lv_label_set_text(iconLabel_, iconText);
    } else {
        lv_label_set_text(iconLabel_, "?");
    }

    lv_obj_center(iconLabel_);

    ESP_LOGI(TAG, "Created icon widget (codepoint: 0x%lx) at %d,%d",
             (unsigned long)config_.iconCodepoint, config_.x, config_.y);
    return obj_;
}

void IconWidget::applyStyle() {
    if (obj_ == nullptr) return;

    // Background
    if (config_.bgOpacity > 0) {
        lv_obj_set_style_bg_color(obj_, lv_color_make(
            config_.bgColor.r, config_.bgColor.g, config_.bgColor.b), 0);
        lv_obj_set_style_bg_opa(obj_, config_.bgOpacity, 0);
    }

    // Border radius
    if (config_.borderRadius > 0) {
        lv_obj_set_style_radius(obj_, config_.borderRadius, 0);
    }

    if (config_.borderWidth > 0 && config_.borderOpacity > 0) {
        lv_obj_set_style_border_width(obj_, config_.borderWidth, 0);
        lv_obj_set_style_border_color(obj_, lv_color_make(
            config_.borderColor.r, config_.borderColor.g, config_.borderColor.b), 0);
        lv_obj_set_style_border_opa(obj_, config_.borderOpacity, 0);
    } else {
        lv_obj_set_style_border_width(obj_, 0, 0);
    }

    applyShadowStyle();

    // Apply icon style
    if (iconLabel_ != nullptr) {
        lv_obj_set_style_text_color(iconLabel_, lv_color_make(
            config_.textColor.r, config_.textColor.g, config_.textColor.b), 0);

        // Use icon font
        uint8_t sizeIdx = config_.iconSize < 6 ? config_.iconSize : config_.fontSize;
        if (Fonts::hasIconFont()) {
            lv_obj_set_style_text_font(iconLabel_, Fonts::iconFont(sizeIdx), 0);
        } else {
            // Fallback to text font (won't show correct icon, but won't crash)
            lv_obj_set_style_text_font(iconLabel_, Fonts::bySizeIndex(sizeIdx), 0);
        }
    }
}

void IconWidget::onKnxSwitch(bool value) {
    if (iconLabel_ == nullptr) return;
    if (config_.textSource != TextSource::KNX_DPT_SWITCH) return;

    // Change icon color based on switch state
    if (value) {
        // Use text color for "on" state (default)
        lv_obj_set_style_text_color(iconLabel_, lv_color_make(
            config_.textColor.r, config_.textColor.g, config_.textColor.b), 0);
    } else {
        // Dim color for "off" state (50% brightness)
        lv_obj_set_style_text_color(iconLabel_, lv_color_make(
            config_.textColor.r / 2, config_.textColor.g / 2, config_.textColor.b / 2), 0);
    }
}
