#include <render/integrator.h>
#include <core/properties.h>

struct PixelBoundarySamplingRecord
{
    bool onSurface_S;
    Vector dir_local;
    Vector dir_visible; // vector pointing to the visible region
    Vector dir_edge;
    // for surface vertex
    int shape_id;
    int triangle_id;
    // for volume vertex
    int med_id_S = -1;
    int tet_id_S = -1;
    Vector4 barycentric4_S;
};

struct PixelBoundaryIntegrator : Integrator
{
    PixelBoundaryIntegrator(){};
    PixelBoundaryIntegrator(const Scene &scene){};
    PixelBoundarySegmentInfo normalVelocity(const PixelBoundarySegmentInfo &seg, const Vector &vB, const Vector &n) const;
    Float guidingDensity(const Scene &scene, RenderOptions options, const Array2i &pixelIdx) const;
    ArrayXd guide(const Scene &scene, RenderOptions options, Float weight = 1.) const;
    // generate the sample count map
    ArrayXd getSampleMap(const ArrayXd &guideMap, int sppe0) const;
    ArrayXd getVarMap(SceneAD &sceneAD, RenderOptions options, const ArrayXd &d_image) const;
    Spectrum Li(const Scene &scene, const Ray &ray, const RadianceQueryRecord &rRec) const;
    Properties velocities(const Scene &scene, const PixelBoundarySamplingRecord &pRec) const;
    ArrayXd renderC(const Scene &scene, const RenderOptions &options) const;
    ArrayXd renderD(SceneAD &sceneAD,
                    const RenderOptions &options, const ArrayXd &d_image) const;
    void configure(const Scene &scene);

    mutable ArrayXd guideMap;
};