#pragma once

#include <ptvc/graphics/GpuProgram.h>
#include <ptvc/scene/Component.h>

#include <glm/glm.hpp>

#include <span>

namespace CodeDrawPTVC::components::lensFlare {

    struct Source {
        glm::vec3 worldPosition{0.0f};
        glm::vec3 color{1.0f};
        float intensity = 1.0f;
        float radiusPx = 80.0f;
        float visibility = 1.0f;
        bool enabled = true;
    };

    struct Config {
        bool enabled = true;
        float globalIntensity = 0.98f;

        // Visible emitter/glare proxy at the source position.
        // This is separate from the secondary lens artifacts below.
        float sourceDotIntensity = 1.11f;
        float sourceDotRadiusScale = 11.25f;

        // Shared scale for ghosts, halo, and streaks.
        float artifactRadiusScale = 4.3f;

        float edgeFadeNdc = 0.061f;
        float ghostIntensity = 1.41f;
        float haloIntensity = 0.54f;
        float streakIntensity = 0.49f;
        bool ghosts = true;
        bool halo = true;
        bool streaks = true;
    };

    class LensFlareComponent final : public CodeDrawPTVC::Component {
    public:
        bool enabled = true;
        float intensityScale = 1.0f;
        float angularRadiusRadians = 0.0179f;
        float emitterRadiusWorld = 0.016f;
        float minRadiusPx = 1.0f;
        float maxRadiusPx = 2000.0f;
        float occlusionBias = 0.0f;
    };

    float FocalLengthYPixels(float viewportHeightPx, float fovYRadians);
    float AngularRadiusPixels(float angularRadiusRadians, float focalLengthYPx);
    float EmitterRadiusPixels(float emitterRadiusWorld, float distanceWorld, float focalLengthYPx);
    class LensFlareRenderer {
    public:
        LensFlareRenderer() = default;
        ~LensFlareRenderer();

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

        LensFlareRenderer(LensFlareRenderer&&) = delete;
        LensFlareRenderer& operator=(LensFlareRenderer&&) = delete;

        void Initialize();
        void Shutdown();

        void Render(
            const glm::mat4& viewProj,
            std::span<const Source> sources,
            int viewportW,
            int viewportH,
            const Config& config);

    private:
        CodeDrawPTVC::GpuProgram _program{};
        unsigned int _vao = 0;
    };

}
