#pragma once
#ifndef BSDF_ROUGH_CONDUCTOR_H__
#define BSDF_ROUGH_CONDUCTOR_H__

#include "bsdf.h"
#include "ptr.h"
#include "microfacet.h"

struct RoughConductorBSDF: BSDF
{
    inline RoughConductorBSDF(float alpha, const Spectrum3f &intEta, const Spectrum3f &K)
        : m_distr(alpha), m_eta(intEta.cast<Float>()), m_k(K.cast<Float>()) {}

    // For pyBind
    inline RoughConductorBSDF(float alpha, const Spectrum3f &intEta, const Spectrum3f &K, ptr<float> dAlpha)
        : m_distr(alpha), m_eta(intEta.cast<Float>()), m_k(K.cast<Float>())
    {
        initVelocities(Eigen::Map<Eigen::Array<float, nder, 1> >(dAlpha.get(), nder, 1).cast<Float>());
    }

    inline RoughConductorBSDF(float alpha, const Spectrum3f &intEta, const Spectrum3f &K, ptr<float> dAlpha, ptr<float> dEta, ptr<float> dK)
        : m_distr(alpha), m_eta(intEta.cast<Float>()), m_k(K.cast<Float>())
    {
        initVelocities(Eigen::Map<Eigen::Array<float, nder, 1> >(dAlpha.get(), nder, 1).cast<Float>(),
                       Eigen::Map<Eigen::Array<float, nder, 3> >(dEta.get(), nder, 3).cast<Float>(),
                       Eigen::Map<Eigen::Array<float, nder, 3> >(dK.get(), nder, 3).cast<Float>());
    }

    inline void initVelocities(const Eigen::Array<Float, nder, 1> &dAlpha) {
        m_distr.initVelocities(dAlpha);
    }

    inline void initVelocities(const Eigen::Array<Float, nder, 1> &dAlpha,
                               const Eigen::Array<Float, nder, 3> &dEta, const Eigen::Array<Float, nder, 3> &dK)
    {
        m_distr.initVelocities(dAlpha);
        m_eta.der = dEta;
        m_k.der = dK;
    }

    Spectrum eval(const Intersection &its, const Vector &wo,  EBSDFMode mode = EBSDFMode::ERadiance) const;
    SpectrumAD evalAD(const IntersectionAD &its, const VectorAD &wo,  EBSDFMode mode = EBSDFMode::ERadiance) const;

    Spectrum sample(const Intersection &its, const Array3 &rnd, Vector &wo, Float &pdf, Float &eta,  EBSDFMode mode = EBSDFMode::ERadiance) const;
    Float pdf(const Intersection &its, const Vector &wo) const;

    inline bool isTransmissive() const { return false; }
    inline bool isTwosided() const { return false; }
    inline bool isNull() const { return false; }

    std::string toString() const {
        std::ostringstream oss;
        oss << "BSDF_rough_conductor [" << '\n'
            << "  eta = (" << m_eta(0) << ", " << m_eta(1) << ", " << m_eta(2) << ")\n"
            << "  k = (" << m_k(0) << ", " << m_k(1) << ", " << m_k(2) << ")\n"
            << "]" << std::endl;
        return oss.str();
    }

    MicrofacetDistribution m_distr;
    SpectrumAD m_eta, m_k;
};

#endif //BSDF_ROUGH_CONDUCTOR_H__
