#pragma once
#include "render/OpenGlExtensions.h"
#include <Eigen/Dense>

namespace ZL {

    class ShadowMap {
    private:
        GLuint fbo = 0;
        GLuint depthTexture = 0;
        int resolution;

        Eigen::Vector3f lightDirection;
        Eigen::Matrix4f lightViewMatrix;
        Eigen::Matrix4f lightProjectionMatrix;
        Eigen::Matrix4f lightSpaceMatrix;

        float orthoSize;
        float nearPlane;
        float farPlane;

    public:
        ShadowMap(int resolution = 2048, float orthoSize = 40.0f,
                  float zNear = 0.1f, float zFar = 100.0f);
        ~ShadowMap();

        ShadowMap(const ShadowMap&) = delete;
        ShadowMap& operator=(const ShadowMap&) = delete;

        void setLightDirection(const Eigen::Vector3f& dir);
        void updateLightSpaceMatrix(const Eigen::Vector3f& sceneCenter);

        void bind();
        void unbind();

        GLuint getDepthTexture() const { return depthTexture; }
        int getResolution() const { return resolution; }
        const Eigen::Matrix4f& getLightSpaceMatrix() const { return lightSpaceMatrix; }
        const Eigen::Matrix4f& getLightViewMatrix() const { return lightViewMatrix; }
        const Eigen::Matrix4f& getLightProjectionMatrix() const { return lightProjectionMatrix; }
        const Eigen::Vector3f& getLightDirection() const { return lightDirection; }
    };

} // namespace ZL
