/**
 * \file /core/masschroq_run/masschroqcondorprocess.cpp
 * \date 12/11/2020
 * \author Thomas Renne
 * \brief handles execution of MasschroQ process through condor job
 */

/*******************************************************************************
 * Copyright (c) 2017 Thomas Renne <thomas.renne@e.email>.
 *
 * This file is part of XTPcpp.
 *
 *     XTPcpp 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.
 *
 *     XTPcpp 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 XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Thomas Renne <thomas.renne@e.email> - initial API and
 *implementation
 ******************************************************************************/

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

MassChroQCondorProcess::MassChroQCondorProcess(
  MainWindow *p_main_window,
  WorkMonitorInterface *p_monitor,
  const MassChroQRunBatch masschroq_batch_param)
  : MassChroQBatchProcess(p_main_window, p_monitor, masschroq_batch_param),
    CondorProcess(p_main_window, p_monitor, "MassChroQ")
{
  QSettings settings;
  m_condorRequestMemory =
    settings.value("tandem/condor_request_memory", "10000").toUInt();
  m_condorDiskUsage =
    settings.value("tandem/condor_disk_usage", "1000").toUInt();
}

MassChroQCondorProcess::~MassChroQCondorProcess()
{
}

void
MassChroQCondorProcess::run()
{
  qDebug() << "begin masschroq run through Ht Condor";
  prepareTemporaryDirectory();
  checkMassChroQRunBatch();
  checkMassChroQMLValidity();
  QString submit_file = createCondorSubmitFile();

  qDebug() << "Prepare and check finished";
  QStringList arguments;
  arguments << QFileInfo(submit_file).absoluteFilePath();
  try
    {
      QProcess condor_process;
      condor_process.start(m_condorSubmitCommand, arguments);


      if(!condor_process.waitForStarted())
        {
          throw pappso::PappsoException(
            QObject::tr("HTCondor MassChroQ process failed to start"));
        }

      if(!condor_process.waitForFinished())
        {
          throw pappso::PappsoException(
            QObject::tr("HTCondor MassChroQ process failed to finish"));
        }

      QString condor_error = condor_process.readAllStandardError();
      qDebug() << condor_error;
      if(!condor_error.isEmpty())
        {
          throw pappso::PappsoException(
            QObject::tr("HTCondor MassChroQ process failed :\n%1")
              .arg(condor_error));
        }

      QString condor_out = condor_process.readAllStandardOutput();
      if(condor_out.isEmpty())
        {
          throw pappso::PappsoException(
            QObject::tr("HTCondor MassChroQ process failed :\nThe MassChroQ "
                        "output is empty."));
        }
      else
        {
          qDebug() << "TandemCondorProcess::run readAllStandardOutput OK "
                   << condor_out;
        }

      parseCondorJobNumber(condor_out);
      MassChroQBatchProcess::mp_monitor->setProgressMaximumValue(
        m_condorJobSize);
      qDebug() << "TandemCondorProcess::run job=" << m_condorClusterNumber
               << " size=" << m_condorJobSize;

      QByteArray result           = condor_process.readAll();
      QProcess::ExitStatus Status = condor_process.exitStatus();

      if(Status != 0)
        {
          // != QProcess::NormalExit
          throw pappso::PappsoException(
            QObject::tr("error executing HTCondor Status != 0 : %1 %2\n%3")
              .arg(m_masschroqRunBatch.masschroq_bin_path)
              .arg(arguments.join(" ").arg(result.data())));
        }
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      throw pappso::PappsoException(
        QObject::tr("error launching MassChroQ condor jobs :\n%1")
          .arg(exception_pappso.qwhat()));
    }
  catch(std::exception &exception_std)
    {
      throw pappso::PappsoException(
        QObject::tr(
          "error launching MassChroQ condor jobs (std::exception):\n%1")
          .arg(exception_std.what()));
    }
  surveyCondorJob();

  MassChroQBatchProcess::mp_monitor->finished(
    QObject::tr("1 HTCondor MassCHroQ job finished"));
  qDebug() << "end masschroq run through Ht Condor";
}

QString
MassChroQCondorProcess::createCondorSubmitFile()
{
  QString submit_file_path = QString("%1/submit.txt").arg(mp_tmpDir->path());
  QFile submit_file(submit_file_path);
  QTextStream *p_out = nullptr;

  if(submit_file.open(QIODevice::WriteOnly))
    {
      p_out = new QTextStream();
      p_out->setDevice(&submit_file);

      *p_out << "Universe   = vanilla" << endl;
      *p_out << "notification   = Error" << endl;
      *p_out << "Rank       = Mips" << endl;
      *p_out << "DiskUsage  = " << m_condorDiskUsage << endl;
      *p_out << "request_memory= " << m_condorRequestMemory << endl;
      *p_out << "request_cpus = " << m_masschroqRunBatch.number_cpu << endl;
      *p_out << "Log        = " << mp_tmpDir->path() << "/condor.log" << endl;
      *p_out << "Output        = " << mp_tmpDir->path()
             << "/masschroq.$(Process).out" << endl;
      *p_out << "Error        = " << mp_tmpDir->path()
             << "/masschroq.$(Process).error" << endl;
      *p_out << "Executable = " << m_masschroqRunBatch.masschroq_bin_path
             << endl;
      *p_out << "Arguments        = "
             << "--cpus " << m_masschroqRunBatch.number_cpu << " -t "
             << m_masschroqRunBatch.masschroq_temporary_dir_path;
      if(m_masschroqRunBatch.on_disk)
        {
          *p_out << " --ondisk ";
        }
      if(m_masschroqRunBatch.parse_peptide)
        {
          *p_out << " --parse-peptides";
        }
      *p_out  << " " << m_masschroqRunBatch.masschroqml_path << endl;
      *p_out << "Queue" << endl;
    }
  else
    {
      throw pappso::PappsoException(
        QObject::tr("error : cannot open condor submit file : %1\n")
          .arg(submit_file.fileName()));
    }

  if(p_out != nullptr)
    {
      p_out->flush();
      submit_file.close();
      delete p_out;
    }
  return submit_file_path;
}
