#pragma once
#ifndef BINNED_TOF_PATH_TRACER_AD_PATHSPACE_H__
#define BINNED_TOF_PATH_TRACER_AD_PATHSPACE_H__

#include "tofIntegratorADps.h"
#include "binnedPathADps.h"
#include <tuple>

struct Binned_TofPathTracerAD_PathSpace : Binned_PathTracerAD_PathSpace {
    void render(const Scene &scene, const RenderOptions &options, ptr<float> rendered_image) const override;

    // Interior term
    void renderInterior_ZeroAndOneBounce(const Scene &scene, const RenderOptions &options, ptr<float> rendered_image) const;

    // Direct edges
    void evalEdgeDirect(const Scene &scene, int shape_id, const Edge &rEdge, const RayAD &edgeRay,
        RndSampler *sampler, int max_bounces, EdgeEvaluationRecord &eRec, Float &path_length, 
        std::vector<std::tuple<int, int, Spectrum>> &record, bool quiet = false) const;
    void renderEdgesDirect(const Scene &scene, const RenderOptions &options, ptr<float> rendered_image) const override;
    
    // Indirect edges
    void renderEdges(const Scene &scene, const RenderOptions &options, ptr<float> rendered_image) const override;
    
    // Helper functions
    void weightedImportance(const Scene& scene, RndSampler* sampler, const Intersection& its, int max_depth, bool is_direct,
        const BinnedWeight& weight, std::vector<std::tuple<int, int, Spectrum>>& ret) const;
    void radiance(const Scene& scene, RndSampler* sampler, const Intersection &its, int max_bounces, BinnedWeight &ret) const;
    void traceRayFromEdgeSegement(const Scene &scene, const EdgeEvaluationRecord& eRec, Float edgePdf, int max_depth, RndSampler *sampler,
        std::vector<Spectrum> &image) const override;

    // Returns <path_contribution, idx_bin>.
    std::vector<std::tuple<SpectrumAD, int>> pixelColorAD(const Scene &scene, const RenderOptions &options,
        RndSampler *sampler, int x, int y) const override;

    // Unused 
    Spectrum pixelColor(const Scene &scene, const RenderOptions &options, RndSampler *sampler, Float x, Float y) const override { assert(false); }
    SpectrumAD pixelColorAD(const Scene &scene, const RenderOptions &options, RndSampler *sampler, Float x, Float y) const override { assert(false); };

    std::string getName() const { return "binned_tofPathAD_ps"; }

    mutable bool use_ellipsoidal_for_one_bounce_interior = true;

    mutable bool use_antithetic_interior = true;
};

#endif //BINNED_TOF_PATH_TRACER_AD_PATHSPACE_H__
