#pragma once

#include "GL/gl3w.h"
#include "GL/gl.h"
#include "Shader.hpp"
#include "Types.hpp"

namespace TSE::OpenGL
{
    class BasicOrderedSpriteSetShader : public Shader
    {
    private:
        static BasicOrderedSpriteSetShader* instance;
        mutable bool meshReady = false;
        GLuint meshVBO = 0;
        GLuint meshIBO = 0;
        GLsizei meshVertexCount = 0;   // für DrawArraysInstanced
        GLsizei meshIndexCount  = 0;   // für DrawElementsInstanced
        GLenum  meshPrimitive   = GL_TRIANGLES;
        GLenum meshIndexType = GL_UNSIGNED_SHORT;
        int instanceCount = 0; // eigener Instanzzähler
        GLint   meshPosSize   = 2;         // 2D (Billboard-Formen), für 3D Meshes: 3
        GLsizei meshStride    = sizeof(float) * 2;
        size_t  meshPosOffset = 0;
        GLuint TextureID;
        Vector2 SpriteCount;

    public:
        static BasicOrderedSpriteSetShader* Instance();
        static void Destroy();
        static void Init(float width, float height);
        BasicOrderedSpriteSetShader(std::vector<std::unique_ptr<ShaderPart>>&& parts);
        ~BasicOrderedSpriteSetShader();
        void SetMesh(const void* verts, int vertCount, int stride, int floatCountPerVertex, int posOffsetBytes, GLenum primitive, const void* indices = nullptr, int indexCount = 0, GLenum indexType = GL_UNSIGNED_SHORT);

    protected:
        void OnEnable() const override;
        void OnDisable() const override;
        void OnFlush() override;
        void OnDrawCall(int indexCount) override;
        void OnPostDraw() override;
        void OnSubmit(const Transformable& t, float*& target, TransformationStack& stack, void (*restartDrawcall)(IRenderer&), IRenderer& rnd) override;
    };
} // namespace TSE::GLFW
