#pragma once
#include <render/integrator.h>

struct RndSampler;
struct Ray;

struct VolpathInterior : UnidirectionalPathTracer
{
    Spectrum Li(const Scene &scene, const Ray &ray, RadianceQueryRecord &rRec) const override;
    void LiAD(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res) const override;

    std::string getName() const override { return "Volpath Interior"; }
};

struct VolpathBoundary : UnidirectionalPathTracer
{
    Spectrum Li(const Scene &scene, const Ray &ray, RadianceQueryRecord &rRec) const override;
    void LiAD(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res) const override;

    std::string getName() const override { return "Volpath Boundary"; }
};

struct Volpath2 : Integrator
{
    ArrayXd renderC(const Scene &scene, const RenderOptions &options) const override;
    ArrayXd renderD(SceneAD &sceneAD, const RenderOptions &options, const ArrayXd &d_image) const override;
    std::string getName() const { return "Volpath2"; }
    VolpathInterior volpathInterior;
    VolpathBoundary volpathBoundary;
};

// struct Volpath2 : UnidirectionalPathTracer
// {
//     Spectrum Li(const Scene &scene, const Ray &ray, RadianceQueryRecord &rRec) const override;
//     void LiAD(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res) const override;
//     virtual ArrayXd renderD(SceneAD &sceneAD, const RenderOptions &options, const ArrayXd &d_image) const override;
//     Spectrum pixelColorAD1(SceneAD &sceneAD, PixelQueryRecord &pRec, const Spectrum &_d_res) const;
//     Spectrum LiAD1(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res) const;
//     void pixelColorAD(SceneAD &sceneAD, PixelQueryRecord &pRec, const Spectrum &d_res) const;

//     // estimate the boundary term of the new formulation
//     // taking the upstream gradient and backpropagating it to the d_scene,
//     // and return the boundary term gradient image if necessary.
//     ArrayXs boundaryTerm(SceneAD &sceneAD, const RenderOptions &options, const ArrayXd &d_image);
//     Spectrum boundaryPixelColorAD(SceneAD &sceneAD, PixelQueryRecord &pRec, const Spectrum &d_res);
//     Spectrum boundaryLiAD(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res);

//     ArrayXs interiorTerm(SceneAD &sceneAD, const RenderOptions &options, const ArrayXd &d_image);
//     Spectrum interiorPixelColorAD(SceneAD &sceneAD, PixelQueryRecord &pRec, const Spectrum &d_res);
//     Spectrum interiorLiAD(SceneAD &sceneAD, const Ray &ray, RadianceQueryRecord &rRec, const Spectrum &d_res);

//     std::string getName() const override { return "Volpath2"; }
// };
