/*
 * MIT License
 * Author: Mark Allyn
 *
 * phosphor.h — P7 phosphor simulation using an OpenGL ping-pong FBO.
 *
 * Each frame:
 *   update() runs the sweep shader — decays old energy and adds beam
 *   contributions (range rings + target echoes) for the swept arc.
 *
 *   renderToScreen() runs the display shader — maps energy to P7 RGB
 *   colour and blits the result into the scope circle on the screen.
 *
 * The PhosphorRenderer owns its GL resources; init() must be called
 * after the GL context is current.
 */

#pragma once
#include <glad/glad.h>
#include <string>
#include <array>
#include <vector>
#include "settings.h"
#include "target_buffer.h"

class PhosphorRenderer {
public:
    PhosphorRenderer()  = default;
    ~PhosphorRenderer();

    // Create FBOs, compile shaders, build fullscreen quad VAO.
    // shaderDir: path to the shaders/ directory (with trailing slash).
    bool init(const std::string& shaderDir);

    // Call once per frame BEFORE rendering to the screen.
    // Runs the ping-pong sweep pass.
    void update(
        float  dt,
        float  beamAngle,       // current beam angle, degrees CW from north
        float  beamAnglePrev,   // beam angle previous frame
        const std::array<TargetState, MAX_TARGETS>& targets,
        int    targetCount,
        const float* ringRadii, // normalised range ring radii
        int    ringCount,
        float  maxRangeM        // scope's full-scale range in metres; used to normalise targets
    );

    // Render the accumulated phosphor texture into the scope circle.
    // scopeCX/CY: centre in GL viewport pixels (origin bottom-left).
    void renderToScreen(
        float scopeCX, float scopeCY,
        float scopeRadius,
        float gain
    );

    // Wipe the phosphor buffer to zero (scope switch, startup).
    void clear();

private:
    static GLuint compileProgram(const std::string& vertPath,
                                 const std::string& fragPath);

    void buildQuad();

    GLuint fbo_[2]   = {0, 0};
    GLuint tex_[2]   = {0, 0};
    int    curr_     = 0;          // index of the texture just written

    GLuint sweepProg_    = 0;
    GLuint displayProg_  = 0;
    GLuint quadVAO_      = 0;
    GLuint quadVBO_      = 0;

    int    fboSize_      = PHOSPHOR_FBO_SIZE;
    bool   initialised_  = false;
};
