/* 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 <libmass/DataPointJsPrototype.hpp>
#include <libmass/DataPoint.hpp>

Q_DECLARE_METATYPE(msXpSlibmass::DataPoint *);


namespace msXpSlibmass
{


/*/js/ Class: DataPoint
 */


DataPointJsPrototype::DataPointJsPrototype(QObject *parent) : QObject(parent)
{
}


DataPointJsPrototype::~DataPointJsPrototype()
{
}


DataPoint *
DataPointJsPrototype::thisDataPoint() const
{
  DataPoint *dataPoint = qscriptvalue_cast<DataPoint *>(thisObject().data());

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

  return dataPoint;
}


bool
DataPointJsPrototype::initialize()
{
  QScriptContext *ctx = context();
  int argCount        = ctx->argumentCount();

  if(argCount == 1)
    {
      // The single argument can either be a string or another DataPoint object.

      QScriptValue arg = ctx->argument(0);

      // It is a string
      if(arg.isString())
        return thisDataPoint()->initialize(qscriptvalue_cast<QString>(arg));

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

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

          ctx->throwError(
            "Syntax error: function takes either one string or a DataPoint "
            "object.");

          return -1;
        }

      // It is a DataPoint object
      if(variant.userType() == QMetaType::type("msXpSlibmass::DataPoint"))
        {
          DataPoint dp(qscriptvalue_cast<DataPoint>(arg));

          /*/js/
           * DataPoint.initialize(other)
           *
           * Initialize this DataPoint object with a <DataPoint> object
           *
           * other: <DataPoint> object
           *
           * Ex:
           * var newDp = new DataPoint(123.321,456.654);
           * var otherDp = new DataPoint();
           * otherDp.initialize(newDp);
           * otherDp.key; // --> 123.321
           * otherDp.val; // --> 456.654
           * otherDp.isValid(); // --> true
           */

          thisDataPoint()->initialize(dp);
          return true;
        }
      else
        {
          qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
                   << "QVariant is not a DataPoint!";
          ctx->throwError(
            "Syntax error: function takes either one string or a DataPoint "
            "object.");
        }
    }
  else if(argCount == 2)
    {
      // The argument can be two double values, the (key,val) pair.

      QScriptValue arg1 = ctx->argument(0);
      QScriptValue arg2 = ctx->argument(1);

      if(!arg1.isNumber() || !arg2.isNumber())
        {
          qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
                   << "One or both argument(s) is/are not of the Number type.";

          ctx->throwError(
            "Syntax error: the two arguments must be of the Number type: key "
            "and val.");

          return -1;
        }

      double key = qscriptvalue_cast<double>(arg1);
      double val = qscriptvalue_cast<double>(arg2);


      /*/js/
       * DataPoint.initialize(key, val)
       *
       * Initialize this DataPoint object with two <Number> entities
       *
       * key: <Number> holding the key of this DataPoint
       * val: <Number> holding the value of this DataPoint
       *
       * Ex:
       * var dp = new DataPoint();
       * dp.initialize(123.321,456.654);
       * dp.key; // --> 123.321
       * dp.val; // --> 456.654
       * dp.isValid(); // --> true
       */


      thisDataPoint()->initialize(key, val);
      return true;
    }

  return false;
}


/*/js/
 * DataPoint.isValid()
 *
 * Return if this <DataPoint> object is valid.
 *
 * Ex:
 * var dp = new DataPoint();
 * dp.initialize(123.321,456.654);
 * dp.key; // --> 123.321
 * dp.val; // --> 456.654
 * dp.isValid(); // --> true
 */
bool
DataPointJsPrototype::isValid() const
{
  return thisDataPoint()->isValid();
}


QScriptValue
DataPointJsPrototype::valueOf() const
{
  return thisObject().data();
}


} // namespace msXpSlibmass
