#ifndef _H_POSTPROCESS_H
#define _H_POSTPROCESS_H

#include <SDL_timer.h>
#include <thirdparty/glad/glad.h>
#include <glm/glm.hpp>
#include <limits>
#include <memory>
#include <utility/resourcemanager.h>
#include <graphics/shader.h>
#include <utility/logger.h>
#include <util.h>

class Postprocessor
{
public:
    Postprocessor(const std::shared_ptr<ResourceManager>&);

    enum EFFECT {
        BLUR = 1 << 0,
        SHAKE = 1 << 1,
        NEGATIVE = 1 << 2,
        COLORMOD = 1 << 3,
        GREYSCALE = 1 << 4
    };


    void ApplyEffect(EFFECT effect, float intensity=0.f, float effectDuration=UTIL::INF_TIME, glm::vec3 colorModifer=glm::vec3(0.0f));
    void RemoveEffects(EFFECT effect);
    void RemoveAllEffects();

    void applyPostProcess(bool worldOrHud=0);

private:

    int edge_kernel[9] = {
        -1, -1, -1,
        -1,  8, -1,
        -1, -1, -1
    };
    float blur_kernel[9] = {
        1.0f / 16.0f, 2.0f / 16.0f, 1.0f / 16.0f,
        2.0f / 16.0f, 4.0f / 16.0f, 2.0f / 16.0f,
        1.0f / 16.0f, 2.0f / 16.0f, 1.0f / 16.0f
    };

    unsigned int UBO;
    struct PostProcessData_t {
        alignas(4) int curTime;

        // world
        alignas(4) int dt;
        alignas(16) glm::vec3 colorMod;
        alignas(4) float blurIntensity;
        alignas(4) float blurDuration;
        alignas(4) float shakeIntensity;
        alignas(4) float shakeDuration;
        alignas(4) int curEffects;
        // hud
        alignas(16) glm::vec3 colorMod_hud;
        alignas(4) float blurIntensity_hud;
        alignas(4) float blurDuration_hud;
        alignas(4) float shakeIntensity_hud;
        alignas(4) float shakeDuration_hud;
        alignas(4) int curEffects_hud;
    }postProcessData;

    void tickEffectTime(bool worldOrHud);
    unsigned int lastTime;
    Shader* postProcessShader;
};

#endif // _H_POSTPROCESS_H
