#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H

#include <GL/glew.h>

#include "gaming-core/utils/Size.h"
#include "gaming-core/utils/Array.h"

class Framebuffer final {
public:
    static const int POSITION = 1;
    static const int NORMAL = 2;
    static const int COLOR = 4;
    static const int RED = 8;
    static const int DEPTH = 16;

    Framebuffer(const Size& size, int mode, bool texCompare = false);
    ~Framebuffer();
    Framebuffer(const Framebuffer& other) = delete;
    Framebuffer(Framebuffer&& other) = delete;
    Framebuffer& operator=(const Framebuffer& other) = delete;
    Framebuffer& operator=(Framebuffer&& other) = delete;

    bool hasError() const;
    void bind() const;

    void resize(int width, int height) const;

    void bindPositionTexture(int textureUnit) const;
    void bindNormalTexture(int textureUnit) const;
    void bindColorTexture(int textureUnit) const;
    void bindRedTexture(int textureUnit) const;
    void bindDepthTexture(int textureUnit) const;

private:
    void genTexture(int index, int width, int height);
    void setupTexture(int index, int width, int height, GLuint* attachments, int& counter);
    void bindTexture(int textureUnit, GLuint texture) const;
    const char* getErrorString(GLenum error) const;

    const Size& size;
    int mode;
    Array<GLuint, 5> textures;
    GLuint buffer;
    bool error;

    struct Data final {
        int mask;
        GLint internalFormat;
        GLenum format;
        GLenum type;
    };
    Data data[5];
};

#endif