/**
 * \file /core/tandem_run/tandemrun.cpp
 * \date 25/01/2020
 * \author Olivier Langella
 * \brief actually does really run tandem directly on Bruker's data
 */

/*******************************************************************************
 * Copyright (c) 2020 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of PAPPSOms-tools.
 *
 *     PAPPSOms-tools 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.
 *
 *     PAPPSOms-tools 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 PAPPSOms-tools.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "tandemrun.h"
#include <QDebug>
#include <QFileInfo>
#include <QSettings>
#include <QProcess>
#include <QRegularExpression>
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/exception/exceptioninterrupted.h>
#include "../../utils/utils.h"


TandemRun::TandemRun(const QString &tandem_binary)
{
  setTandemBinaryPath(tandem_binary);
}

TandemRun::~TandemRun()
{
}

void
TandemRun::setTandemBinaryPath(const QString &tandem_binary_path)
{


  m_tandemBinary = tandem_binary_path;
  QSettings settings;
  if(m_tandemBinary.isEmpty())
    {
      m_tandemBinary =
        settings.value("path/tandem_binary", "/usr/bin/tandem").toString();
    }
  // check for tandem executable
  m_tandemVersion = Utils::checkXtandemVersion(m_tandemBinary);

  qDebug() << m_tandemVersion;
  settings.setValue("path/tandem_binary", m_tandemBinary);
}


void
TandemRun::readyReadStandardOutput()
{
  QString message(m_xtProcess->readAllStandardOutput());
  mp_monitor->appendText(message);

  if(message.toLower().contains("error"))
    {
      throw pappso::PappsoException(message);
    }

  if(mp_monitor->shouldIstop())
    {
      m_xtProcess->kill();
      delete m_xtProcess;
      m_xtProcess = nullptr;
      throw pappso::ExceptionInterrupted(
        QObject::tr("X!Tandem stopped by the user"));
    }
}

void
TandemRun::readyReadStandardError()
{
  mp_monitor->appendText(m_xtProcess->readAllStandardError());
  if(mp_monitor->shouldIstop())
    {
      m_xtProcess->kill();
      delete m_xtProcess;
      m_xtProcess = nullptr;
      throw pappso::ExceptionInterrupted(
        QObject::tr("X!Tandem stopped by the user"));
    }
}

void
TandemRun::run(pappso::UiMonitorInterface &monitor,
               const QString &tandem_input_file)
{
  mp_monitor = &monitor;

  runTandem(tandem_input_file);
  mp_monitor = nullptr;
}
void
TandemRun::runTandem(const QString &tandem_input_file)
{
  if(mp_monitor->shouldIstop())
    {
      throw pappso::ExceptionInterrupted(
        QObject::tr("X!Tandem stopped by the user processing on file %1")
          .arg(tandem_input_file));
    }
  m_xtProcess = new QProcess();
  QStringList arguments;

  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();

  arguments << tandem_input_file;
  // hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
  m_xtProcess->start(m_tandemBinary, arguments);

  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();

  connect(m_xtProcess,
          &QProcess::readyReadStandardOutput,
          this,
          &TandemRun::readyReadStandardOutput);
  connect(m_xtProcess,
          &QProcess::readyReadStandardError,
          this,
          &TandemRun::readyReadStandardError);


  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();

  mp_monitor->setStatus(QObject::tr("Running X!Tandem"));

  if(!m_xtProcess->waitForStarted())
    {
      throw pappso::PappsoException(
        QObject::tr("X!Tandem process failed to start"));
    }

  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
  while(m_xtProcess->waitForFinished(m_maxTandemRunTimeMs) == false)
    {
      //_p_monitor->appendText(xt_process->readAll().data());
      // data.append(xt_process->readAll());
      if(mp_monitor->shouldIstop())
        {
          m_xtProcess->kill();
          delete m_xtProcess;
          m_xtProcess = nullptr;
          throw pappso::ExceptionInterrupted(
            QObject::tr("X!Tandem stopped by the user processing on file %1")
              .arg(tandem_input_file));
        }
    }

  QProcess::ExitStatus Status = m_xtProcess->exitStatus();

  delete m_xtProcess;
  if(Status != QProcess::ExitStatus::NormalExit)
    {
      // != QProcess::NormalExit
      throw pappso::PappsoException(
        QObject::tr("error executing X!Tandem Status != 0 : %1")
          .arg(m_tandemBinary));
    }
  m_xtProcess = nullptr;
}
