//**********************************************************************************
//    Copyright (C) 2009-2019  Ovidio Pena <ovidio@bytesfall.com>
//    Copyright (C) 2013-2019  Konstantin Ladutenko <kostyfisik@gmail.com>
//
//    This file is part of scattnlay
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    The only additional remark is that we expect that all publications
//    describing work using this software, or all commercial products
//    using it, cite at least one of the following references:
//    [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by
//        a multilayered sphere," Computer Physics Communications,
//        vol. 180, Nov. 2009, pp. 2348-2354.
//    [2] K. Ladutenko, U. Pal, A. Rivera, and O. Pena-Rodriguez, "Mie
//        calculation of electromagnetic near-field for a multilayered
//        sphere," Computer Physics Communications, vol. 214, May 2017,
//        pp. 225-230.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//    @brief  Wrapper to JS
//
//**********************************************************************************
#include "nmie-precision.hpp"
#include "nmie-web-impl.hpp"

using namespace emscripten;

nmie::MultiLayerMieWeb<double> ml_mie;

EMSCRIPTEN_BINDINGS(c) {
  class_<nmie::MultiLayerMieWeb<double>>("nmie")
      .constructor<>()
      .function("SetWavelength", &nmie::MultiLayerMieWeb<double>::SetWavelength)
      .function("AddTargetLayerReIm",
                &nmie::MultiLayerMieWeb<double>::AddTargetLayerReIm)
      .function("SetModeNmaxAndType",
                &nmie::MultiLayerMieWeb<double>::SetModeNmaxAndType)
      .function("ClearTarget", &nmie::MultiLayerMieWeb<double>::ClearTarget)
      .function("RunMieCalculation",
                &nmie::MultiLayerMieWeb<double>::RunMieCalculation)
      .function("RunFieldCalculationPolar",
                &nmie::MultiLayerMieWeb<double>::RunFieldCalculationPolar)
      .function("RunFieldCalculationCartesian",
                &nmie::MultiLayerMieWeb<double>::RunFieldCalculationCartesian)
      .function("GetFieldEabs", &nmie::MultiLayerMieWeb<double>::GetFieldEabs)
      .function("GetQsca", &nmie::MultiLayerMieWeb<double>::GetQsca)
      .function("GetQext", &nmie::MultiLayerMieWeb<double>::GetQext)
      .function("GetQabs", &nmie::MultiLayerMieWeb<double>::GetQabs)
      //              .function("bf",&nmie::MultiLayerMieWeb<double>::bf)
      ;
}

// namespace nmie {
//**********************************************************************************
//  This function emulates a C call to calculate the actual scattering
//  parameters and amplitudes.
//
//  Input parameters:
//    L: Number of layers
//    pl: Index of PEC layer. If there is none just send -1
//    x: Array containing the size parameters of the layers [0..L-1]
//    m: Array containing the relative refractive indexes of the layers [0..L-1]
//    nTheta: Number of scattering angles
//    Theta: Array containing all the scattering angles where the scattering
//           amplitudes will be calculated
//    nmax: Maximum number of multipolar expansion terms to be used for the
//          calculations. Only use it if you know what you are doing, otherwise
//          set this parameter to -1 and the function will calculate it
//
//  Output parameters:
//    Qext: Efficiency factor for extinction
//    Qsca: Efficiency factor for scattering
//    Qabs: Efficiency factor for absorption (Qabs = Qext - Qsca)
//    Qbk: Efficiency factor for backscattering
//    Qpr: Efficiency factor for the radiation pressure
//    g: Asymmetry factor (g = (Qext-Qpr)/Qsca)
//    Albedo: Single scattering albedo (Albedo = Qsca/Qext)
//    S1, S2: Complex scattering amplitudes
//
//  Return value:
//    Number of multipolar expansion terms used for the calculations
//**********************************************************************************
//  int nMieWeb(const unsigned int L, const int pl, std::vector<double> &x,
//  std::vector<std::complex<double> > &m, const unsigned int nTheta,
//  std::vector<double> &Theta, const int nmax, double *Qext, double *Qsca,
//  double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo,
//  std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >&
//  S2) {
//
//    if (x.size() != L || m.size() != L)
//        throw std::invalid_argument("Declared number of layers do not fit x
//        and m!");
//    if (Theta.size() != nTheta)
//        throw std::invalid_argument("Declared number of sample for Theta is
//        not correct!");
//    try {
//      MultiLayerMieWeb<FloatType> ml_mie;
//      ml_mie.SetLayersSize(ConvertVector<FloatType>(x));
//      ml_mie.SetLayersIndex(ConvertComplexVector<FloatType>(m));
//      ml_mie.SetAngles(ConvertVector<FloatType>(Theta));
//      ml_mie.SetPECLayer(pl);
//      ml_mie.SetMaxTerms(nmax);
//
//      ml_mie.RunMieCalculation();
//
//      *Qext = static_cast<double>(ml_mie.GetQext());
//      *Qsca = static_cast<double>(ml_mie.GetQsca());
//      *Qabs = static_cast<double>(ml_mie.GetQabs());
//      *Qbk = static_cast<double>(ml_mie.GetQbk());
//      *Qpr = static_cast<double>(ml_mie.GetQpr());
//      *g = static_cast<double>(ml_mie.GetAsymmetryFactor());
//      *Albedo = static_cast<double>(ml_mie.GetAlbedo());
//      S1 = ConvertComplexVector<double>(ml_mie.GetS1());
//      S2 = ConvertComplexVector<double>(ml_mie.GetS2());
//
//      return ml_mie.GetMaxTerms();
//    } catch(const std::invalid_argument& ia) {
//      // Will catch if  ml_mie fails or other errors.
//      std::cerr << "Invalid argument: " << ia.what() << std::endl;
//      throw std::invalid_argument(ia);
//      return -1;
//    }
//    return 0;
//  }
//  int nMieWeb(const unsigned int L, std::vector<double>& x,
//  std::vector<std::complex<double> >& m, const unsigned int nTheta,
//  std::vector<double>& Theta, double *Qext, double *Qsca, double *Qabs, double
//  *Qbk, double *Qpr, double *g, double *Albedo,
//  std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >&
//  S2) {
//    return nmie::nMieWeb(L, -1, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs,
//    Qbk, Qpr, g, Albedo, S1, S2);
//  }
//  int nMieWeb(const unsigned int L, const int pl, std::vector<double>& x,
//  std::vector<std::complex<double> >& m, const unsigned int nTheta,
//  std::vector<double>& Theta, double *Qext, double *Qsca, double *Qabs, double
//  *Qbk, double *Qpr, double *g, double *Albedo,
//  std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >&
//  S2) {
//    return nmie::nMieWeb(L, pl, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs,
//    Qbk, Qpr, g, Albedo, S1, S2);
//  }
//  int nMieWeb(const unsigned int L, std::vector<double>& x,
//  std::vector<std::complex<double> >& m, const unsigned int nTheta,
//  std::vector<double>& Theta, const int nmax, double *Qext, double *Qsca,
//  double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo,
//  std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >&
//  S2) {
//    return nmie::nMieWeb(L, -1, x, m, nTheta, Theta, nmax, Qext, Qsca, Qabs,
//    Qbk, Qpr, g, Albedo, S1, S2);
//  }
// ********************************************************************** //
// ********************************************************************** //
// ********************************************************************** //

//}  // end of namespace nmie
