// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "BSDF.ih"
#include "Fresnel.ih"

OSPRAY_BEGIN_ISPC_NAMESPACE

// FIXME: improve robustness
struct Dielectric
{
  BSDF super;

  float eta; // etaO / etaI
};

inline BSDF_EvalRes Dielectric_eval(
    const varying BSDF *uniform, const vec3f &, const vec3f &)
{
  return make_BSDF_EvalRes_zero();
}

inline BSDF_SampleRes Dielectric_sample(
    const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float ss)
{
  const varying Dielectric *uniform self =
      (const varying Dielectric *uniform)super;
  BSDF_SampleRes res;

  float cosThetaO = max(dot(wo, getN(super)), 0.f);

  // Fresnel term
  float cosThetaT; // positive
  float F = fresnelDielectricEx(cosThetaO, cosThetaT, self->eta);
  res.pdf = inf;

  // Sample the reflection or the transmission
  bool doReflection = (ss <= F);
  if (doReflection) {
    // Reflection
    res.wi = reflect(wo, getN(super), cosThetaO);
    res.type = BSDF_SPECULAR_REFLECTION;
    res.weight = make_vec3f(1.f);
  } else {
    // Transmission
    res.wi = refract(wo, getN(super), cosThetaO, cosThetaT, self->eta);
    res.type = BSDF_SPECULAR_TRANSMISSION;
    // res.weight = make_vec3f(sqr(self->eta)); // solid angle compression
    res.weight = make_vec3f(1.f); // ignore solid angle compression
  }

  return res;
}

inline void Dielectric_Constructor(varying Dielectric *uniform self,
    const varying linear3f *uniform frame,
    float eta)
{
  BSDF_Constructor(&self->super,
      make_vec3f(1.0f),
      BSDF_SPECULAR,
      BSDF_TYPE_DIELECTRIC,
      frame);
  self->eta = eta;
}

inline varying BSDF *uniform Dielectric_create(
    uniform ShadingContext *uniform ctx,
    const varying linear3f *uniform frame,
    float eta)
{
  varying Dielectric *uniform self = (varying Dielectric * uniform)
      ShadingContext_alloc(ctx, sizeof(Dielectric));
  Dielectric_Constructor(self, frame, eta);
  return &self->super;
}

// Helper function for transparent shadow rays
inline vec3f Dielectric_getTransparency(float cosThetaO, float eta)
{
  float T = 1.f - fresnelDielectric(cosThetaO, eta);
  return make_vec3f(T);
}

OSPRAY_END_ISPC_NAMESPACE
