#pragma once

#include <extra2d/graphics/resources/pipeline.h>
#include <glad/glad.h>
#include <cstdint>

namespace extra2d {

// ============================================================================
// OpenGL 管线状态实现
// ============================================================================
class GLPipeline : public Pipeline {
public:
    /**
     * @brief 构造函数
     */
    GLPipeline();

    /**
     * @brief 析构函数
     */
    ~GLPipeline() override;

    /**
     * @brief 初始化管线
     * @param desc 管线描述
     * @return 成功返回 true
     */
    bool init(const PipelineDesc& desc);

    /**
     * @brief 关闭管线，释放资源
     */
    void shutdown();

    // Pipeline 接口实现
    void bind() override;
    void unbind() override;
    void setBlendMode(BlendMode mode) override;
    BlendMode getBlendMode() const override { return blendMode_; }
    void setDepthTest(bool enabled) override;
    void setDepthWrite(bool enabled) override;
    void setDepthFunc(DepthFunc func) override;
    void setCullMode(CullMode mode) override;
    bool isValid() const override { return initialized_; }
    uintptr_t getNativeHandle() const override { return 0; }  // OpenGL 管线没有单一句柄

    /**
     * @brief 设置视口
     * @param x 视口左下角X坐标
     * @param y 视口左下角Y坐标
     * @param width 视口宽度
     * @param height 视口高度
     */
    void setViewport(int x, int y, int width, int height);

    /**
     * @brief 获取当前视口
     * @param x 输出X坐标
     * @param y 输出Y坐标
     * @param width 输出宽度
     * @param height 输出高度
     */
    void getViewport(int& x, int& y, int& width, int& height) const;

    /**
     * @brief 应用所有状态（用于初始化或重置）
     */
    void applyAllStates();

private:
    bool initialized_ = false;

    // 当前状态
    BlendMode blendMode_ = BlendMode::Alpha;
    bool blendEnabled_ = true;
    bool depthTest_ = false;
    bool depthWrite_ = false;
    DepthFunc depthFunc_ = DepthFunc::Less;
    CullMode cullMode_ = CullMode::None;

    // 视口
    int viewportX_ = 0;
    int viewportY_ = 0;
    int viewportWidth_ = 0;
    int viewportHeight_ = 0;

    // 状态缓存（避免冗余 GL 调用）
    BlendMode cachedBlendMode_ = BlendMode::None;
    bool cachedBlendEnabled_ = false;
    bool cachedDepthTest_ = false;
    bool cachedDepthWrite_ = false;
    DepthFunc cachedDepthFunc_ = DepthFunc::Less;
    CullMode cachedCullMode_ = CullMode::None;
    int cachedViewportX_ = -1;
    int cachedViewportY_ = -1;
    int cachedViewportWidth_ = -1;
    int cachedViewportHeight_ = -1;

    /**
     * @brief 应用混合状态
     */
    void applyBlendState();

    /**
     * @brief 应用深度状态
     */
    void applyDepthState();

    /**
     * @brief 应用裁剪状态
     */
    void applyCullState();

    /**
     * @brief 转换混合模式到 OpenGL 枚举
     */
    static void getBlendFactors(BlendMode mode, GLenum& srcFactor, GLenum& dstFactor);

    /**
     * @brief 转换深度函数到 OpenGL 枚举
     */
    static GLenum convertDepthFunc(DepthFunc func);

    /**
     * @brief 转换裁剪模式到 OpenGL 枚举
     */
    static GLenum convertCullMode(CullMode mode);
};

} // namespace extra2d
