#pragma once

#include "integrator.h"

namespace psdr
{

PSDR_CLASS_DECL_BEGIN(DirectIntegratorNRF, final, Integrator)
public:
    DirectIntegratorNRF(int bsdf_samples = 1, int light_samples = 1, int edge_direct = 1);
    virtual ~DirectIntegratorNRF();

    void preprocess_secondary_edges(const Scene &scene, const std::vector<int> &sensor_id, const std::vector<float> &config, int option = 0) override;

    FloatC get_grid();
    std::pair<Vector3fC, Vector3fC> get_AQ_grid();
    
    bool m_hide_emitters = false;

protected:
    SpectrumC Li(const Scene &scene, Sampler &sampler, const RayC &ray, MaskC active = true) const override;
    SpectrumD Li(const Scene &scene, Sampler &sampler, const RayD &ray, MaskD active = true) const override;

    template <bool ad>
    Spectrum<ad> __Li(const Scene &scene, Sampler &sampler, const Ray<ad> &ray, Mask<ad> active) const;

    void render_secondary_edges(const Scene &scene, int sensor_id, SpectrumD &result) const override;

    template <bool ad>
    std::pair<IntC, Spectrum<ad>> eval_secondary_edge(const Scene &scene, const Sensor &sensor, const Vector3fC &sample3) const;

    SpectrumC                   __eval_secondary_edge(const Scene &scene, const std::vector<int> &active_sensor, const Vector3fC &sample3) const;

    int m_bsdf_samples, m_light_samples, m_edge_direct;
    std::vector<HyperCubeDistribution3f*> m_warpper;
    std::vector<AdaptiveQuadratureDistribution3f*>      m_aq;
    AdaptiveQuadratureDistribution3f*                   m_global_aq = nullptr;
    int preprocess_option = -1;

PSDR_CLASS_DECL_END(DirectIntegrator)

} // namespace psdr
