#include "adapters/unity/chams/resources/ChamsShaderRepository.h"

#include "adapters/unity/chams/resources/ChamsBundleRuntime.h"
#include "adapters/il2cpp/Il2CppResolver.h"
#include "adapters/il2cpp/Il2CppObjectAccess.h"
#include "adapters/il2cpp/Il2CppString.h"

namespace ta::adapters::unity::chams
{
    Il2CppObject* ChamsShaderRepository::resolve(
        const Il2CppImage* unity_image,
        const char* shader_name)
    {
        ChamsBundleRuntime& runtime = ChamsBundleRuntime::instance();
        Il2CppObject* current_bundle = runtime.current_bundle();
        if (!unity_image || !current_bundle || !shader_name || !*shader_name)
            return nullptr;

        if (unity_image_ != unity_image || bundle_ != current_bundle)
        {
            unity_image_ = unity_image;
            bundle_ = current_bundle;
            shader_system_type_ = nullptr;
            shaders_.clear();
        }

        if (!shader_system_type_)
            shader_system_type_ = ta::adapters::il2cpp::get_system_type(unity_image, "UnityEngine", "Shader");
        if (!shader_system_type_)
            return nullptr;

        const auto found = shaders_.find(shader_name);
        if (found != shaders_.end())
            return found->second;

        Il2CppObject* shader = runtime.load_asset(shader_name, shader_system_type_);
        if (shader)
            shaders_.emplace(shader_name, shader);
        return shader;
    }

    void ChamsShaderRepository::reset() noexcept
    {
        unity_image_ = nullptr;
        bundle_ = nullptr;
        shader_system_type_ = nullptr;
        shaders_.clear();
    }

    ChamsShaderRepository& shader_repository() noexcept
    {
        static ChamsShaderRepository repository;
        return repository;
    }
}
