/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2018 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


/////////////////////// Qt includes
#include <QDebug>
#include <QScriptEngine>


/////////////////////// Local includes
#include <minexpert/nongui/SavGolFilterJsPrototype.hpp>

#include <globals/globals.hpp>


namespace msXpSmineXpert
{


/*/js/ Class: SavGolFilter
 */


SavGolFilterJsPrototype::SavGolFilterJsPrototype(QObject *parent)
  : QObject(parent)
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";
}


SavGolFilterJsPrototype::~SavGolFilterJsPrototype()
{
}


SavGolFilter *
SavGolFilterJsPrototype::thisSavGolFilter() const
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  SavGolFilter *savGolFilter =
    qscriptvalue_cast<SavGolFilter *>(thisObject().data());

  if(savGolFilter == Q_NULLPTR)
    qFatal(
      "Fatal error at %s@%d -- %s. "
      "thisSavGolFilter() would return Q_NULLPTR."
      "Program aborted.",
      __FILE__,
      __LINE__,
      __FUNCTION__);

  return savGolFilter;
}


int
SavGolFilterJsPrototype::initialize()
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  // Depending on the various parameters, we will choose the proper
  // initializing function.

  QScriptContext *ctx = context();
  int argCount        = ctx->argumentCount();

  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
  //<< "argCount: " << argCount;

  if(argCount == 1)
    {
      return initializeOneArgument();
    }
  else if(argCount == 5)
    {
      return initializeFiveArguments();
    }

  return -1;
}


// Return the number of arguments used for the initialization or -1 on error
int
SavGolFilterJsPrototype::initializeOneArgument()
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  QScriptContext *ctx = context();
  int argCount        = ctx->argumentCount();

  if(argCount != 1)
    qFatal(
      "Fatal error at %s@%d -- %s(). "
      "Programming error."
      "Program aborted.",
      __FILE__,
      __LINE__,
      __FUNCTION__);

  // There is only one argument. We need to check the type of that argument
  // and depending on that type choose the proper initializator.

  QScriptValue arg = ctx->argument(0);

  // The other single-arg initializations are with Trace or SavGolFilter.

  QVariant variant = arg.data().toVariant();

  if(!variant.isValid())
    {
      qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
               << "Variant is not valid";

      ctx->throwError("Syntax error: function takes a SavGolFilter object.");

      return -1;
    }

  if(variant.userType() == QMetaType::type("msXpSmineXpert::SavGolFilter"))
    {
      SavGolFilter savGolFilter(qscriptvalue_cast<SavGolFilter>(arg));

      thisSavGolFilter()->initialize(savGolFilter);

      /*/js/
       * SavGolFilter.initialize(other)
       *
       * Initialize this SavGolFilter object with another
       * <SavGolFilter> object
       *
       * other: <SavGolFilter> object used to initialize this object
       */

      return 1;
    }

  return -1;
}


// Return the number of arguments used for the initialization or -1 on error.
int
SavGolFilterJsPrototype::initializeFiveArguments()
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  QScriptContext *ctx = context();
  int argCount        = ctx->argumentCount();

  if(argCount != 4)
    qFatal(
      "Fatal error at %s@%d -- %s(). "
      "Programming error."
      "Program aborted.",
      __FILE__,
      __LINE__,
      __FUNCTION__);

  QScriptValue arg1 = ctx->argument(0);
  QScriptValue arg2 = ctx->argument(1);
  QScriptValue arg3 = ctx->argument(2);
  QScriptValue arg4 = ctx->argument(3);
  QScriptValue arg5 = ctx->argument(5);

  if(!arg1.isNumber() || !arg2.isNumber() || !arg3.isNumber() ||
     !arg4.isNumber() || !arg5.isBoolean())
    {
      qDebug()
        << __FILE__ << __LINE__ << __FUNCTION__ << "()"
        << "One or more arguments is/are not of the Number or Boolean type.";

      ctx->throwError(
        "Syntax error: expected Savitzky-Golay parameters, nL, "
        "nR, m, lD and convolveWithNr.");

      return -1;
    }

  int nL              = qscriptvalue_cast<int>(arg1);
  int nR              = qscriptvalue_cast<int>(arg2);
  int m               = qscriptvalue_cast<int>(arg3);
  int lD              = qscriptvalue_cast<int>(arg4);
  bool convolveWithNr = qscriptvalue_cast<bool>(arg4);

  SavGolParams params;

  params.nL             = nL;
  params.nR             = nR;
  params.m              = m;
  params.lD             = lD;
  params.convolveWithNr = convolveWithNr;

  thisSavGolFilter()->initialize(params);

  /*/js/
   * SavGolFilter.initialize(nL, nR, m, lD, convolveWithNr)
   *
   * Initialize this SavGolFilter object with parameters to configure the
   * SavGolParams member object
   *
   * nL: number of data points on the left of the point being filtered
   * nR: number of data points on the right of the point being filtered
   * m: order of the polynomial to use in the regression analysis
   * leading to the Savitzky-Golay coefficients (typicall [2-6])
   * lD: order of the derivative to extract from the Savitzky-Golay
   * smoothing algorithm (for regular smoothing, use 0);
   * convolveWithNr: set to false for best results
   */
  return 5;
}


/*/js/
 * SavGolFilter.asText()
 *
 * Return a <String> object containing a textual representation of all the
 * member data of this SavGolFilter object.
 */
QString
SavGolFilterJsPrototype::asText() const
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  return thisSavGolFilter()->asText();
}


QScriptValue
SavGolFilterJsPrototype::valueOf() const
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()";

  return thisObject().data();
}


} // namespace msXpSmineXpert
