#pragma once

#include <vector>
#include <string>

#include "RHI/RHICommond.h"

#include "Core/Core.h"


class GLVAOCreateCommand : public RHICommond {
public:
    GLVAOCreateCommand(
        Mesh* mesh,
        uint32 vaoHandle,
        uint32 vboHandle,
        uint32 eboHandle
    );
    ~GLVAOCreateCommand() override;

protected:
    void OnExecute() override;

private:
    unsigned char* vertex_{ nullptr };
    uint32 vertexCount_{ 0 };
    uint32* indices_{ nullptr };
    uint32 indicesCount_{ 0 };

    uint32 vaoHandle_{ 0 };
    uint32 vao_{ 0 };
    uint32 vboHandle_{ 0 };
    uint32 vbo_{ 0 };
    uint32 eboHandle_{ 0 };
    uint32 ebo_{ 0 };
};

class GLDrawArrayCommand : public RHICommond {
public:
    GLDrawArrayCommand(
        uint32 vaoHandle,
        uint32 vaoStart,
        uint32 vaoCount
    );
    ~GLDrawArrayCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 vaoHandle_{ 0 };
    uint32 vaoStart_{ 0 };
    uint32 vaoCount_{ 0 };
};

class GLDrawElementsCommand : public RHICommond {
public:
    GLDrawElementsCommand(
        uint32 vaoHandle,
        uint32 eboHandle,
        uint32 eboCount
    );
    ~GLDrawElementsCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 vaoHandle_{ 0 };
    uint32 eboHandle_{ 0 };
    uint32 eboCount_{ 0 };
};

class GLVAODeleteCommand : public RHICommond {
public:
    GLVAODeleteCommand(
        uint32 vaoHandle,
        uint32 vboHandle,
        uint32 eboHandle
    );
    ~GLVAODeleteCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 vaoHandle_{ 0 };
    uint32 vboHandle_{ 0 };
    uint32 eboHandle_{ 0 };
};

class GLShaderCreateCommand : public RHICommond {
public:
    GLShaderCreateCommand(
        uint32 shaderHandle,
        uint32 type,
        const std::string& shader
    );
    ~GLShaderCreateCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 shaderHandle_{ 0 };
    std::string shader_;
    uint32 type_{ 0 };
};

class GLShaderDeleteCommand : public RHICommond {
public:
    GLShaderDeleteCommand(
        uint32 shaderHandle
    );
    ~GLShaderDeleteCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 shaderHandle_{ 0 };
};

class GLProgramCreateCommand : public RHICommond {
public:
    GLProgramCreateCommand(
        uint32 programHandle,
        std::vector<uint32> shaders
    );
    ~GLProgramCreateCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 programHandle_{ 0 };
    std::vector<uint32> shaders_;
};

class GLProgramUseCommand : public RHICommond {
public:
    GLProgramUseCommand(
        uint32 programHandle,
        bool use
    );
    ~GLProgramUseCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 programHandle_{ 0 };
    bool use_;
};

class GLProgramDeleteCommand : public RHICommond {
public:
    GLProgramDeleteCommand(
        uint32 programHandle
    );
    ~GLProgramDeleteCommand() override = default;

protected:
    void OnExecute() override;

private:
    uint32 programHandle_{ 0 };
};

class GLStartCommand : public RHICommond {
public:
    GLStartCommand();
    virtual ~GLStartCommand() = default;

protected:
    void OnExecute() override;

private:
    int32 width_{ 1 };
    int32 height_{ 1 };
};

class GLEndCommand : public RHICommond {
public:
    GLEndCommand();
    virtual ~GLEndCommand();

protected:
    void OnExecute() override;
};
