/**
 * \file core/python/pythonqprocess.cpp
 * \date 23/06/2023
 * \author Olivier Langella
 * \brief Overload the Qprocess for the python process
 */

/*******************************************************************************
 * Copyright (c) 2023 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.fr>.
 *
 * This file is part of i2MassChroQ.
 *
 *     i2MassChroQ 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.
 *
 *     i2MassChroQ 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 i2MassChroQ.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "pythonqprocess.h"
#include <QDebug>
#include <QSettings>
#include <pappsomspp/core/pappsoexception.h>

PythonQProcess::PythonQProcess(QObject *parent) : QProcess(parent)
{
  // startRProcess();
  m_rscriptTextStream.setString(&m_rscriptCode);
}

PythonQProcess::~PythonQProcess()
{
  stopRprocess();
}


void
PythonQProcess::startRprocess()
{
  QString version_return;
  QSettings settings;
  QString r_binary_path = settings.value("path/python_binary", "python").toString();


  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
  env.insert("LANGUAGE", "en_US.UTF-8");
  setProcessEnvironment(env);

  QStringList arguments;


  qDebug() << readAllStandardOutput();

  arguments.clear();
  arguments << "-u";

  start(r_binary_path, arguments, QProcess::Append | QProcess::ReadWrite);

  if(!waitForStarted())
    {
      QString err = tr("Could not start python process '%1' with arguments '%2': %3")
                      .arg(r_binary_path)
                      .arg(arguments.join(QStringLiteral(" ")))
                      .arg(errorString());
      throw pappso::PappsoException(err);
    }
}

void
PythonQProcess::stopRprocess()
{

  qDebug();
  if(state() == QProcess::Running)
    {
      qDebug();
      executeOffTheRecord(QString("quit( save = \"no\");"));
      qDebug() << readAllStandardOutput();
      waitForFinished(1000);
      qDebug();
      QProcess::ExitStatus Status = exitStatus();
      qDebug() << Status;
      if(Status != 0)
        {
          // != QProcess::NormalExit
          kill();
          // delete mp_rProcess;
          throw pappso::PappsoException(
            QObject::tr("error executing R Status != 0 "));
        }
    }
  qDebug();
}


qint64
PythonQProcess::executeOnTheRecord(const QString &mcqr_code)
{
  QString in_code(mcqr_code);
  in_code.replace("&quot;", "\"");
  m_rscriptTextStream << in_code;
  return QProcess::write(in_code.toUtf8());
}

const QString &
PythonQProcess::getRscriptCode() const
{
  return m_rscriptCode;
}

qint64
PythonQProcess::executeOffTheRecord(const QString &mcqr_otr)
{
  qDebug() << mcqr_otr;
  return QProcess::write(mcqr_otr.toUtf8());
}


void
PythonQProcess::executeMcqrStep(const QString &mcqr_step_name,
                              const QString &mcqr_step)
{

  executeOnTheRecord(
    QString("message(\"MCQRBegin: %1\")\n").arg(mcqr_step_name));

  executeOffTheRecord("vl <- tryCatch({\n");
  executeOnTheRecord(mcqr_step);

  executeOnTheRecord(QString("message(\"MCQREnd: %1\")\n").arg(mcqr_step_name));
  // write(mcqr_step.toUtf8());
  executeOffTheRecord(
    QString(
      "\n},error "
      "= function(err) {\n message(paste(\"Error in %1 : \",err))\n},finally = "
      "function(f) "
      "{\n print(paste(\"e: \", e))\n})\n message(paste(\"Output: \", vl))\n")
      .arg(mcqr_step_name));
}
