#include <extra2d/graphics/core/render_module.h>
#include <extra2d/graphics/backends/backend_factory.h>
#include <extra2d/graphics/backends/opengl/gl_shader.h>
#include <extra2d/graphics/shader/shader_manager.h>
#include <extra2d/core/registry.h>
#include <extra2d/core/service_locator.h>
#include <extra2d/app/application.h>
#include <extra2d/platform/window_module.h>
#include <extra2d/utils/logger.h>
#include <filesystem>

namespace extra2d {

// 前向声明后端初始化函数
namespace graphics {
#ifdef E2D_BACKEND_OPENGL
void initOpenGLBackend();
#endif
#ifdef E2D_BACKEND_VULKAN
void initVulkanBackend();
#endif
}

RenderModule::RenderModule(std::function<void(RenderCfg&)> configFn) {
    configFn(cfg_);
}

RenderModule::~RenderModule() {
    if (initialized_) {
        shutdown();
    }
}

static std::string getExecutableDir() {
    try {
        auto currentPath = std::filesystem::current_path();
        return currentPath.string() + "/";
    } catch (...) {
        return "./";
    }
}

bool RenderModule::init() {
    if (initialized_) return true;
    
    auto* winMod = Registry::instance().get<WindowModule>();
    if (!winMod || !winMod->win()) {
        E2D_LOG_ERROR("WindowModule not available");
        return false;
    }
    
    // 初始化图形后端（注册到工厂）
#ifdef E2D_BACKEND_OPENGL
    graphics::initOpenGLBackend();
#endif
#ifdef E2D_BACKEND_VULKAN
    graphics::initVulkanBackend();
#endif
    
    if (!ShaderManager::getInstance().isInitialized()) {
        auto factory = makeShared<GLShaderFactory>();
        std::string shaderDir = getExecutableDir() + "shaders/";
        std::string cacheDir = getExecutableDir() + "shader_cache/";
        if (!ShaderManager::getInstance().init(shaderDir, cacheDir, factory)) {
            E2D_LOG_WARN("Failed to initialize ShaderManager with dir: {}", shaderDir);
        }
    }
    
    std::string windowBackend = winMod->getWindowBackend();
    
    if (cfg_.backend.empty()) {
        E2D_LOG_INFO("No graphics backend specified, auto-selecting for window backend: {}", windowBackend);
        renderer_ = graphics::BackendFactory::createBackendForWindow(windowBackend);
    } else {
        if (!graphics::BackendFactory::isCompatible(cfg_.backend, windowBackend)) {
            E2D_LOG_WARN("Graphics backend '{}' is not compatible with window backend '{}'", 
                        cfg_.backend, windowBackend);
        }
        renderer_ = graphics::BackendFactory::createBackend(cfg_.backend);
    }
    
    if (!renderer_) {
        E2D_LOG_ERROR("Failed to create render backend");
        return false;
    }
    
    if (!renderer_->init(winMod->win())) {
        E2D_LOG_ERROR("Failed to initialize render backend");
        renderer_.reset();
        return false;
    }
    
    E2D_LOG_INFO("Render module initialized successfully");
    initialized_ = true;
    return true;
}

void RenderModule::shutdown() {
    if (!initialized_) return;
    
    if (renderer_) {
        renderer_->shutdown();
        renderer_.reset();
    }
    
    initialized_ = false;
}

} // namespace extra2d
