#pragma once
#ifndef AREA_EMITTER_H__
#define AREA_EMITTER_H__

#include <render/emitter.h>

struct AreaLight : Emitter
{
    AreaLight(){};
    AreaLight(int shape_id, const Spectrum &intensity)
        : Emitter(shape_id), intensity(intensity){};

    Emitter *clone() const override
    {
        return new AreaLight(*this);
    }
    void merge(Emitter *emitter) override
    {
        intensity += dynamic_cast<AreaLight *>(emitter)->intensity;
    };
    void setZero() override
    {
        intensity.setZero();
    }

    inline int getShapeID() const { return shape_id; }
    Spectrum getIntensity() const { return intensity; }

    Float pdf(const Intersection &its, const Vector &d) const;

    // Return the radiant emittance for the given surface intersection
    Spectrum eval(const Intersection &its, const Vector &d) const;

    Spectrum eval(const Vector &norm, const Vector &d) const;

    Float evalDirection(const Vector &norm, const Vector &d) const;

    Float sampleDirection(const Array2 &rnd, Vector &dir,
                          Float *pdf = nullptr) const;

    Spectrum sampleDirect(const Vector2 &rnd, DirectSamplingRecord &dRec) const;
    Spectrum samplePosition(const Vector2 &rnd, PositionSamplingRecord &pRec) const
    {
        assert(false);
        return Spectrum::Zero();
    }
    std::string toString() const override
    {
        std::ostringstream oss;
        oss << "AreaLight[" << std::endl
            << "  intensity = "
            << ::toString(intensity)
            << std::endl
            << "  shape_id = " << shape_id << std::endl
            << "]" << std::endl;
        return oss.str();
    }

    Spectrum intensity;

    PSDR_IMPLEMENT_VIRTUAL_CLASS(AreaLight)
    PSDR_DECLARE_CLASS(AreaLight)
};

#endif // AREA_EMITTER_H__
