#include "SpriteComponent.h"
#include "../core/utils/AssetManager.h"
#include "../core/utils/Logging.h"
#include <GL/glew.h>



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

bool SpriteComponent::HasTexture()
{
    return texture_loaded;
}



void SpriteComponent::SetTexture(const std::string &path)
{
    if (path.empty()) return;

    AssetManager::LoadAssetAsync(path, AssetType::Image);
    const auto* asset = AssetManager::GetAssetByPath(path);
    if (asset)
        SetTexture(asset->uaid);
}



void SpriteComponent::SetNormalMap(const std::string &path)
{
    if (path.empty()) return;

    AssetManager::LoadAssetAsync(path, AssetType::Image);
    const auto* asset = AssetManager::GetAssetByPath(path);
    if (asset)
        SetNormalMap(asset->uaid);
}



void SpriteComponent::SetTexture(uint64_t uaid)
{
    textureUAID = uaid;
    const auto* asset = AssetManager::GetAssetByID(uaid);
    if (asset && asset->loaded)
    {
        if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
        {
            textureID = imageAsset->textureID;
            size = imageAsset->size;
            texture_loaded = true;
        }
        else
        {
            Logger::LogError("[SpriteComponent] Asset with UAID '%llu' is not an image!", uaid);
        }
    }
}




void SpriteComponent::SetNormalMap(uint64_t uaid)
{
    normalMapUAID = uaid;
    const auto* asset = AssetManager::GetAssetByID(uaid);
    if (asset && asset->loaded)
    {
        if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
        {
            normalMapID = imageAsset->textureID;
        }
        else
        {
            Logger::LogError("[SpriteComponent] Asset with UAID '%llu' is not an image!", uaid);
        }
    }
}




unsigned int SpriteComponent::GetTextureID() const
{
    return textureID;
}



unsigned int SpriteComponent::GetNormalMapID() const
{
    return normalMapID;
}



uint64_t SpriteComponent::GetTextureUAID() const
{
    return textureUAID;
}



uint64_t SpriteComponent::GetNormalMapUAID() const
{
    return normalMapUAID;
}



void SpriteComponent::Save(YAML::Emitter &out) const
{
    out << YAML::BeginMap;
    out << YAML::Key << "type" << YAML::Value << "SpriteComponent";
    out << YAML::Key << "texture" << YAML::Value << textureUAID;
    out << YAML::Key << "normalMap" << YAML::Value << normalMapUAID;
    out << YAML::Key << "renderType" << YAML::Value << (renderType == RenderType::Lit ? "Lit" : "Unlit");
    out << YAML::EndMap;
}



void SpriteComponent::Load(const YAML::Node& node)
{
    try {
        if (node["texture"])
            SetTexture(node["texture"].as<uint64_t>());

        if (node["normalMap"])
            SetNormalMap(node["normalMap"].as<uint64_t>());

        if (node["renderType"] && node["renderType"].IsScalar()) {
            std::string typeStr = node["renderType"].as<std::string>();
            if (typeStr == "Lit")        renderType = RenderType::Lit;
            else if (typeStr == "Unlit") renderType = RenderType::Unlit;
            else
                RecoverableError("Invalid 'renderType' value in SpriteComponent: " + typeStr,
                                 Create::Exceptions::InvalidFormat).Handle();
        }

    } catch (const YAML::Exception& e) {
        RecoverableError("YAML parsing error in SpriteComponent::Load: " + std::string(e.what()),
                         Create::Exceptions::ComponentLoad).Handle();
    }
}
