#include "TextComponent.h"
#include "../core/utils/AssetManager.h"

using namespace core::types;

TextComponent::TextComponent(Object *owner)
    : Component(owner)
{
}

void TextComponent::SetText(const std::string &t)
{
    m_text = t;
}
const std::string &TextComponent::GetText() const
{
    return m_text;
}

void TextComponent::SetFontUAID(uint64_t fontUAID)
{
    m_fontUAID = fontUAID;
}
uint64_t TextComponent::GetFontUAID() const
{
    return m_fontUAID;
}

const FontAssetInfo *TextComponent::GetFontAsset() const
{
    auto info = AssetManager::GetAssetByID(m_fontUAID);
    return (info && info->type == AssetType::Font)
               ? static_cast<const FontAssetInfo *>(info)
               : nullptr;
}

void TextComponent::SetFontSize(float s)
{
    m_fontSize = s;
}
float TextComponent::GetFontSize() const
{
    return m_fontSize;
}

void TextComponent::SetColor(const Color &c)
{
    m_color = c;
}
const Color &TextComponent::GetColor() const
{
    return m_color;
}

void TextComponent::SetWrapWidth(float w)
{
    m_wrapWidth = w;
}
float TextComponent::GetWrapWidth() const
{
    return m_wrapWidth;
}

void TextComponent::SetAlignment(HorizontalAlign h, VerticalAlign v)
{
    m_hAlign = h;
    m_vAlign = v;
}
void TextComponent::GetAlignment(HorizontalAlign &h, VerticalAlign &v) const
{
    h = m_hAlign;
    v = m_vAlign;
}

void TextComponent::EnableShadow(const Vec2 &off, const Color &col)
{
    m_shadowEnabled = true;
    m_shadowOffset = off;
    m_shadowColor = col;
}
void TextComponent::DisableShadow()
{
    m_shadowEnabled = false;
}

void TextComponent::EnableOutline(float thickness, const Color &col)
{
    m_outlineEnabled = true;
    m_outlineThickness = thickness;
    m_outlineColor = col;
}
void TextComponent::DisableOutline()
{
    m_outlineEnabled = false;
}

void TextComponent::Save(YAML::Emitter &out) const
{
    try
    {
        out << YAML::BeginMap;

        out << YAML::Key << "type" << YAML::Value << GetName();
        out << YAML::Key << "Text" << YAML::Value << m_text;
        out << YAML::Key << "FontUAID" << YAML::Value << m_fontUAID;
        out << YAML::Key << "FontSize" << YAML::Value << m_fontSize;
        out << YAML::Key << "Color" << YAML::Flow << YAML::Value
            << YAML::BeginSeq << m_color.r << m_color.g << m_color.b << m_color.a << YAML::EndSeq;
        out << YAML::Key << "WrapWidth" << YAML::Value << m_wrapWidth;
        out << YAML::Key << "HAlign" << YAML::Value << int(m_hAlign);
        out << YAML::Key << "VAlign" << YAML::Value << int(m_vAlign);

        out << YAML::Key << "ShadowEnabled" << YAML::Value << m_shadowEnabled;
        if (m_shadowEnabled)
        {
            out << YAML::Key << "ShadowOffset" << YAML::Flow << YAML::Value
                << YAML::BeginSeq << m_shadowOffset.x << m_shadowOffset.y << YAML::EndSeq;
            out << YAML::Key << "ShadowColor" << YAML::Flow << YAML::Value
                << YAML::BeginSeq << m_shadowColor.r << m_shadowColor.g << m_shadowColor.b << m_shadowColor.a << YAML::EndSeq;
        }

        out << YAML::Key << "OutlineEnabled" << YAML::Value << m_outlineEnabled;
        if (m_outlineEnabled)
        {
            out << YAML::Key << "OutlineThickness" << YAML::Value << m_outlineThickness;
            out << YAML::Key << "OutlineColor" << YAML::Flow << YAML::Value
                << YAML::BeginSeq << m_outlineColor.r << m_outlineColor.g << m_outlineColor.b << m_outlineColor.a << YAML::EndSeq;
        }
        out << YAML::EndMap;
    }
    catch (const YAML::Exception &e)
    {
        Logger::LogError("[TextComponent::Save] YAML emit failed: %s", e.what());
    }
}

void TextComponent::Load(const YAML::Node &node)
{
    try
    {
        if (!node || !node.IsMap())
            return;

        if (auto n = node["Text"]; n && n.IsScalar())
            m_text = n.as<std::string>();

        if (auto n = node["FontUAID"]; n && n.IsScalar())
            m_fontUAID = n.as<UAssetID>();

        if (auto n = node["FontSize"]; n && n.IsScalar())
            m_fontSize = n.as<float>();

        if (auto n = node["Color"]; n && n.IsSequence() && n.size() >= 4)
        {
            m_color.r = n[0].as<float>();
            m_color.g = n[1].as<float>();
            m_color.b = n[2].as<float>();
            m_color.a = n[3].as<float>();
        }

        if (auto n = node["WrapWidth"]; n && n.IsScalar())
            m_wrapWidth = n.as<float>();

        if (auto n = node["HAlign"]; n && n.IsScalar())
            m_hAlign = static_cast<HorizontalAlign>(n.as<int>());

        if (auto n = node["VAlign"]; n && n.IsScalar())
            m_vAlign = static_cast<VerticalAlign>(n.as<int>());

        m_shadowEnabled = node["ShadowEnabled"] ? node["ShadowEnabled"].as<bool>() : false;
        if (m_shadowEnabled)
        {
            if (auto n = node["ShadowOffset"]; n && n.IsSequence() && n.size() >= 2)
            {
                m_shadowOffset.x = n[0].as<float>();
                m_shadowOffset.y = n[1].as<float>();
            }
            if (auto n = node["ShadowColor"]; n && n.IsSequence() && n.size() >= 4)
            {
                m_shadowColor.r = n[0].as<float>();
                m_shadowColor.g = n[1].as<float>();
                m_shadowColor.b = n[2].as<float>();
                m_shadowColor.a = n[3].as<float>();
            }
        }

        m_outlineEnabled = node["OutlineEnabled"] ? node["OutlineEnabled"].as<bool>() : false;
        if (m_outlineEnabled)
        {
            if (auto n = node["OutlineThickness"]; n && n.IsScalar())
                m_outlineThickness = n.as<float>();
            if (auto n = node["OutlineColor"]; n && n.IsSequence() && n.size() >= 4)
            {
                m_outlineColor.r = n[0].as<float>();
                m_outlineColor.g = n[1].as<float>();
                m_outlineColor.b = n[2].as<float>();
                m_outlineColor.a = n[3].as<float>();
            }
        }
    }
    catch (const YAML::Exception &e)
    {
        Logger::LogError("[TextComponent::Load] YAML parse failed: %s", e.what());
    }
}
