#include "area.h"
#include <render/intersection.h>

Spectrum AreaLight::eval(const Intersection &its, const Vector &d) const
{
    if (its.geoFrame.n.dot(d) > Epsilon)
        return intensity;
    else
        return Spectrum::Zero();
}

Spectrum AreaLight::eval(const Vector &norm, const Vector &d) const
{
    if (norm.dot(d) > Epsilon)
        return intensity;
    else
        return Spectrum::Zero();
}

Float AreaLight::evalDirection(const Vector &norm, const Vector &d) const
{
    Float dp = norm.dot(d);
    if (dp > Epsilon)
        return dp;
    else
        return 0.;
}

Float AreaLight::sampleDirection(const Array2 &rnd, Vector &dir,
                                 Float *pdf) const
{
    dir = squareToCosineHemisphere(Vector2(rnd[0], rnd[1]));
    if (pdf)
        *pdf = squareToCosineHemispherePdf(dir);
    return M_PI;
}

Spectrum AreaLight::sampleDirect(const Vector2 &rnd,
                                 DirectSamplingRecord &dRec) const
{
    shape_ptr->samplePosition(rnd, dRec);
    Vector dir = dRec.p - dRec.ref;
    Float dist = dir.norm();
    const Vector &light_norm = dRec.n;
    dir /= dist;
    dRec.dist = dist;
    dRec.dir = dir;
    Float G = dRec.n.dot(-dir) / (dist * dist);
    dRec.G = G;
    assert(dRec.pdf != 0);
    if (dRec.dir.dot(dRec.n) < 0 && dRec.pdf != 0)
    {
        dRec.emittance = eval(light_norm, -dir);
        return eval(light_norm, -dir) * G * dRec.J / detach(dRec.pdf);
    }
    else
    {
        dRec.emittance = Spectrum::Zero();
        return Spectrum::Zero();
    }
}

Float AreaLight::pdf(const Intersection &its, const Vector &d) const
{
    return squareToCosineHemispherePdf(d);
}