#include "pch.h"
#include "app.h"
#include "legacy_gl_runtime_dispatch.h"
#include "renderer_api/shader_catalog.h"
#include "renderer_gl/opengl_capabilities.h"
#include "shader.h"

namespace {

void apply_shader_manager_feature_state(pp::renderer::gl::OpenGlFeatureState feature_state) noexcept
{
    ShaderManager::ext_framebuffer_fetch = feature_state.capabilities.framebuffer_fetch;
    ShaderManager::ext_map_aligned = feature_state.capabilities.map_buffer_alignment;
    ShaderManager::ext_float32 = feature_state.capabilities.float32_textures;
    ShaderManager::ext_float32_linear = feature_state.capabilities.float32_linear;
    ShaderManager::ext_float16 = feature_state.capabilities.float16_textures;
    ShaderManager::set_render_device_features(feature_state.features);
}

}

void App::initShaders()
{
#ifdef _DEBUG
    if (!check_uniform_uniqueness())
        LOG("check_uniform_uniqueness() failed");
#endif // _DEBUG

    render_task([] {
        const auto detection_result = pp::renderer::gl::query_opengl_capability_detection(
            pp::legacy::gl_runtime::extension_query_dispatch(),
            pp::renderer::gl::opengl_runtime_for_current_build());
        if (!detection_result.ok()) {
            LOG("OpenGL capability detection failed: %s", detection_result.status().message);
            return;
        }

        const auto& detection = detection_result.value();
        for (const auto& extension : detection.extensions) {
            LOG("EXT: %s", extension.c_str());
        }

        apply_shader_manager_feature_state(detection.feature_state);
    });
    
    apply_shader_manager_feature_state(pp::renderer::gl::detect_opengl_feature_state(
        std::span<const std::string_view> {},
        pp::renderer::gl::opengl_runtime_for_current_build()));

    LOG("Shader Extension shader_framebuffer_fetch: %s", ShaderManager::ext_framebuffer_fetch ? "enabled" : "disabled");

    LOG("initializing shaders");
    const auto shader_catalog = pp::renderer::panopainter_shader_catalog();
    const auto catalog_status = pp::renderer::validate_shader_catalog(shader_catalog);
    if (!catalog_status.ok())
    {
        LOG("Shader catalog validation failed: %s", catalog_status.message);
        return;
    }

    for (const auto& shader : shader_catalog)
    {
        if (!ShaderManager::load(static_cast<kShader>(const_hash(shader.name)), shader.path))
            LOG("Failed to create shader %s", shader.name);
    }
    LOG("shaders initialized");
}


