#include <psdr/core/ray.h>
#include <psdr/core/intersection.h>
#include <psdr/bsdf/bsdf.h>
#include <psdr/emitter/emitter.h>
#include <psdr/shape/mesh.h>
#include <psdr/scene/scene.h>
#include <psdr/bsdf/microfacet.h>
#include <psdr/integrator/collocated_nrf.h>

namespace psdr
{

SpectrumC CollocatedIntegratorNRF::Li(const Scene &scene, Sampler &sampler, const RayC &ray, MaskC active) const {
    return __Li<false>(scene, ray, active);
}


SpectrumD CollocatedIntegratorNRF::Li(const Scene &scene, Sampler &sampler, const RayD &ray, MaskD active) const {
    return __Li<true>(scene, ray, active);
}

template <bool ad>
Spectrum<ad> CollocatedIntegratorNRF::__Li(const Scene &scene, const Ray<ad> &ray, Mask<ad> active) const {
    TriangleInfoD *triangles = new TriangleInfoD();
    Intersection<ad> its = scene.ray_intersect<ad>(ray, active, triangles);
    Spectrum<ad> result;
    active &= its.is_valid();

    Microfacet bsdf(Bitmap3fD(its.specular), Bitmap3fD(its.diffuse), Bitmap1fD(its.roughness));
    result = bsdf.eval(its, its.wi, active)/sqr(its.t);

    if constexpr (ad) {
        result *= m_intensity;
    } else {
        result *= detach(m_intensity);
    }

    delete triangles;

    return result;
}

} // namespace psdr
