/**
 * \file /output/mcqr/mcqrdata.cpp
 * \date 05/01/2021
 * \author Thomas Renne
 * \brief write Rdata used by MCQR
 */

/*******************************************************************************
 * Copyright (c) 2021 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 "mcqrdata.h"
#include <QDebug>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <pappsomspp/pappsoexception.h>
#include <pappsomspp/utils.h>
#include <QProcess>
#include <QSettings>
#include <grantlee/template.h>
#include <grantlee/engine.h>
#include <QTemporaryDir>


McqrRdata::McqrRdata(McqrExperimentSp mcqr_experiment_sp, ProjectSp project)
{
  msp_project        = project;
  msp_mcqrExperiment = mcqr_experiment_sp;
}

McqrRdata::~McqrRdata()
{
}


void
McqrRdata::writeSpectralCountData(pappso::UiMonitorInterface &monitor)
{

  // mcqr_experiment_sp.get()->getRdataFilePath();
  QString rdata_dir =
    QFileInfo(msp_mcqrExperiment.get()->getRdataFilePath()).absolutePath();
  qDebug() << " rdata_path=" << msp_mcqrExperiment.get()->getRdataFilePath();
  QTemporaryDir *tmp_rdata_dir_p = new QTemporaryDir(rdata_dir + "/output");
  tmp_rdata_dir_p->setAutoRemove(true);

  if(!tmp_rdata_dir_p->isValid())
    {
      throw pappso::PappsoException(
        QObject::tr(
          "problem creating Rdata writing temporary directory in %1\n")
          .arg(rdata_dir));
    }

  monitor.setTitle(QObject::tr("writing MCQR metadata file, please wait"));

  QFileInfo meta_rdata_path(tmp_rdata_dir_p->path() + "/meta.RData");
  writeMetaDataTable(meta_rdata_path);


  monitor.setTitle(QObject::tr("writing MCQR summary file, please wait"));
  QFileInfo summary_rdata_path(tmp_rdata_dir_p->path() + "/summary.RData");
  writeExperimentalSummaryTable(summary_rdata_path);

  monitor.setTitle(
    QObject::tr("writing MCQR spectral count file, please wait"));
  QFileInfo sc_rdata_path(tmp_rdata_dir_p->path() + "/sc.RData");
  writeSpectraCountTable(sc_rdata_path);

  monitor.setTitle(
    QObject::tr("writing MCQR quantification info file, please wait"));
  QFileInfo quanti_rdata_path(tmp_rdata_dir_p->path() + "/quanti.RData");
  writeQuantiInfoTable(quanti_rdata_path);

  monitor.setTitle(QObject::tr("Merging MCQR rdata files, please wait"));
  QString rscript_path = McqrRdata::createTheMergeRScript(
    tmp_rdata_dir_p->path(), msp_mcqrExperiment.get()->getRdataFilePath(),
    msp_mcqrExperiment.get()->getMassChroqMlFilePath());
  McqrRdata::mergeTheRDataFiles(rscript_path);
  tmp_rdata_dir_p->remove();
}


ssize_t
McqrRdata::write_data(const void *bytes, size_t len, void *ctx)
{
  int fd = *(int *)ctx;
  return write(fd, bytes, len);
}

void
McqrRdata::closeMCQRDataFile()
{
  rdata_end_file(mp_rdataWriter);
  close(m_rdataFile);
}


void
McqrRdata::writeMetaDataTable(const QFileInfo &meta_datafile)
{

  m_rdataFile =
    open(meta_datafile.absoluteFilePath().toUtf8(), O_CREAT | O_WRONLY, 0664);
  mp_rdataWriter = rdata_writer_init(&write_data, RDATA_WORKSPACE);
  rdata_begin_file(mp_rdataWriter, &m_rdataFile);


  std::vector<McqrMetadata *> metadata_lines =
    msp_project->getMcqrExperimentSp().get()->getmetadataInfoVector();
  std::vector<QString> colnames =
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns();
  std::vector<rdata_column_t *> columns = createMetadataColumns();

  rdata_begin_table(mp_rdataWriter, "metadata.data");

  for(std::size_t i = 0; i < colnames.size(); i++)
    {
      rdata_column_t *column_writer = columns[i];

      rdata_begin_column(mp_rdataWriter, column_writer, metadata_lines.size());
      if(colnames[i] == "msrun")
        {
          for(McqrMetadata *metadata : metadata_lines)
            {
              rdata_append_string_value(mp_rdataWriter,
                                        metadata->m_msrunId.toUtf8());
            }
        }
      else if(colnames[i] == "msrunfile")
        {
          for(McqrMetadata *metadata : metadata_lines)
            {
              rdata_append_string_value(mp_rdataWriter,
                                        metadata->m_msrunFile.toUtf8());
            }
        }
      else
        {
          if(column_writer->type == RDATA_TYPE_STRING)
            {
              for(McqrMetadata *metadata : metadata_lines)
                {
                  rdata_append_string_value(
                    mp_rdataWriter,
                    metadata->m_otherData[column_writer->name].toByteArray());
                }
            }
          else if(column_writer->type == RDATA_TYPE_REAL)
            {
              for(McqrMetadata *metadata : metadata_lines)
                {
                  rdata_append_real_value(
                    mp_rdataWriter,
                    metadata->m_otherData[column_writer->name].toDouble());
                }
            }
          else if(column_writer->type == RDATA_TYPE_LOGICAL)
            {
              for(McqrMetadata *metadata : metadata_lines)
                {
                  rdata_append_logical_value(
                    mp_rdataWriter,
                    metadata->m_otherData[column_writer->name].toBool());
                }
            }
          else
            {
              throw pappso::PappsoException(
                QObject::tr("The given type isn't recognize : %1")
                  .arg(column_writer->type));
            }
        }
      rdata_end_column(mp_rdataWriter, column_writer);
    }
  rdata_end_table(mp_rdataWriter, metadata_lines.size(), "Metadata info");

  closeMCQRDataFile();
}

std::vector<rdata_column_t *>
McqrRdata::createMetadataColumns()
{
  std::vector<QString> colnames =
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns();
  std::vector<rdata_column_t *> columns;

  for(QString col_name : colnames)
    {
      rdata_column_t *col_writer;
      if(col_name == "msrun" || col_name == "msrunfile")
        {
          col_writer = rdata_add_column(mp_rdataWriter, col_name.toUtf8(),
                                        RDATA_TYPE_STRING);
        }
      else
        {
          QVariant::Type type = msp_project->getMcqrExperimentSp()
                                  .get()
                                  ->getmetadataInfoVector()
                                  .front()
                                  ->m_otherData[col_name]
                                  .type();

          if(type == QVariant::Type::Double)
            {
              qDebug() << "double : " << col_name;
              col_writer = rdata_add_column(mp_rdataWriter, col_name.toUtf8(),
                                            RDATA_TYPE_REAL);
            }
          else if(type == QVariant::Type::Bool)
            {
              qDebug() << "bool : " << col_name;
              col_writer = rdata_add_column(mp_rdataWriter, col_name.toUtf8(),
                                            RDATA_TYPE_LOGICAL);
            }
          else if(type == QVariant::Type::String)
            {
              qDebug() << "string : " << col_name;
              col_writer = rdata_add_column(mp_rdataWriter, col_name.toUtf8(),
                                            RDATA_TYPE_STRING);
            }
          else
            {
              throw pappso::PappsoException(
                QObject::tr("The given type isn't recognize : %1").arg(type));
            }
        }
      columns.push_back(col_writer);
    }
  return columns;
}

void
McqrRdata::writeSpectraCountTable(const QFileInfo &sctable_datafile)
{

  m_rdataFile    = open(sctable_datafile.absoluteFilePath().toUtf8(),
                     O_CREAT | O_WRONLY, 0664);
  mp_rdataWriter = rdata_writer_init(&write_data, RDATA_WORKSPACE);
  rdata_begin_file(mp_rdataWriter, &m_rdataFile);

  rdata_column_t *col_protein =
    rdata_add_column(mp_rdataWriter, "protein", RDATA_TYPE_STRING);
  rdata_column_t *col_msrun =
    rdata_add_column(mp_rdataWriter, "msrun", RDATA_TYPE_STRING);
  rdata_column_t *col_msrunfile =
    rdata_add_column(mp_rdataWriter, "msrunfile", RDATA_TYPE_STRING);
  rdata_column_t *col_acc =
    rdata_add_column(mp_rdataWriter, "accession", RDATA_TYPE_STRING);
  rdata_column_t *col_desc =
    rdata_add_column(mp_rdataWriter, "description", RDATA_TYPE_STRING);
  rdata_column_t *col_sc =
    rdata_add_column(mp_rdataWriter, "sc", RDATA_TYPE_REAL);
  rdata_column_t *col_specific_sc =
    rdata_add_column(mp_rdataWriter, "specific_sc", RDATA_TYPE_REAL);
  std::size_t row_count = getNumberOfRow(true);
  qDebug() << "Number of SC row count " << row_count;
  rdata_begin_table(mp_rdataWriter, "sc.data");

  int nb_line = 0;
  // Append protein column
  rdata_begin_column(mp_rdataWriter, col_protein, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> &group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              for(std::size_t i = 0;
                  i < msp_project->getMsRunStore().getMsRunList().size(); i++)
                {
                  QString protein_id =
                    protein_match->getGrpProteinSp().get()->getGroupingId();
                  rdata_append_string_value(mp_rdataWriter,
                                            protein_id.toUtf8());
                  nb_line++;
                }
            }
        }
    }
  qDebug() << nb_line;
  rdata_end_column(mp_rdataWriter, col_protein);

  // Append msrun id column
  rdata_begin_column(mp_rdataWriter, col_msrun, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match [[maybe_unused]] :
              group_pair.second.get()->getProteinMatchList())
            {
              for(MsRunSp msrun_sp :
                  msp_project->getMsRunStore().getMsRunList())
                {
                  rdata_append_string_value(mp_rdataWriter,
                                            msrun_sp->getXmlId().toUtf8());
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_msrun);

  // Append msrun file column
  rdata_begin_column(mp_rdataWriter, col_msrunfile, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match [[maybe_unused]] :
              group_pair.second.get()->getProteinMatchList())
            {
              for(MsRunSp msrun_sp :
                  msp_project->getMsRunStore().getMsRunList())
                {
                  rdata_append_string_value(mp_rdataWriter,
                                            msrun_sp->getFileName().toUtf8());
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_msrunfile);

  // Append accession column
  rdata_begin_column(mp_rdataWriter, col_acc, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              for(std::size_t i = 0;
                  i < msp_project->getMsRunStore().getMsRunList().size(); i++)
                {
                  QString protein_acc =
                    protein_match->getProteinXtpSp()->getAccession();
                  rdata_append_string_value(mp_rdataWriter,
                                            protein_acc.toUtf8());
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_acc);

  // Append Description column
  rdata_begin_column(mp_rdataWriter, col_desc, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              for(std::size_t i = 0;
                  i < msp_project->getMsRunStore().getMsRunList().size(); i++)
                {
                  QString protein_desc =
                    protein_match->getProteinXtpSp()->getDescription();
                  rdata_append_string_value(mp_rdataWriter,
                                            protein_desc.toUtf8());
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_desc);

  // Append Spectral count column
  rdata_begin_column(mp_rdataWriter, col_sc, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              for(MsRunSp ms_runsp :
                  msp_project->getMsRunStore().getMsRunList())
                {
                  std::size_t protein_sc = protein_match->countSampleScan(
                    ValidationState::validAndChecked, ms_runsp.get());
                  rdata_append_real_value(mp_rdataWriter, protein_sc);
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_sc);

  // Append Specific spectral count column
  rdata_begin_column(mp_rdataWriter, col_specific_sc, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              for(MsRunSp ms_runsp :
                  msp_project->getMsRunStore().getMsRunList())
                {
                  std::size_t protein_sc =
                    protein_match->getGroupingGroupSp()
                      .get()
                      ->countSpecificSampleScan(
                        protein_match, ValidationState::validAndChecked,
                        ms_runsp.get());
                  rdata_append_real_value(mp_rdataWriter, protein_sc);
                }
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_specific_sc);
  rdata_end_table(mp_rdataWriter, row_count, "Spectral count data");

  closeMCQRDataFile();
}

std::size_t
McqrRdata::getNumberOfRow(bool is_spectral_count)
{
  std::size_t row_count = 0;
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          std::size_t nb_msrun;
          if(is_spectral_count)
            {
              nb_msrun = msp_project->getMsRunStore().getMsRunList().size();
            }
          else
            {
              nb_msrun = 1;
            }
          std::size_t number_of_protein_by_group =
            group_pair.second.get()->getProteinMatchList().size() * nb_msrun;
          row_count += number_of_protein_by_group;
        }
    }
  return row_count;
}

void
McqrRdata::writeQuantiInfoTable(const QFileInfo &quanti_info_datafile)
{
  m_rdataFile    = open(quanti_info_datafile.absoluteFilePath().toUtf8(),
                     O_CREAT | O_WRONLY, 0664);
  mp_rdataWriter = rdata_writer_init(&write_data, RDATA_WORKSPACE);
  rdata_begin_file(mp_rdataWriter, &m_rdataFile);


  rdata_column_t *col_protein =
    rdata_add_column(mp_rdataWriter, "accession", RDATA_TYPE_STRING);
  rdata_column_t *col_nbaa =
    rdata_add_column(mp_rdataWriter, "nb_aa", RDATA_TYPE_REAL);
  rdata_column_t *col_nbpepth =
    rdata_add_column(mp_rdataWriter, "nb_peptide_theo", RDATA_TYPE_REAL);
  rdata_column_t *col_mass =
    rdata_add_column(mp_rdataWriter, "mass_Da", RDATA_TYPE_REAL);
  std::size_t row_count = getNumberOfRow(false);

  rdata_begin_table(mp_rdataWriter, "quanti.data");

  // Append protein column
  rdata_begin_column(mp_rdataWriter, col_protein, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              QString protein_id =
                protein_match->getGrpProteinSp().get()->getAccession();
              rdata_append_string_value(mp_rdataWriter, protein_id.toUtf8());
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_protein);

  // Append number of aa column
  rdata_begin_column(mp_rdataWriter, col_nbaa, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              int protein_nbaa = protein_match->getProteinXtpSp()->size();
              rdata_append_real_value(mp_rdataWriter, protein_nbaa);
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_nbaa);

  // Append theoric peptide number column
  rdata_begin_column(mp_rdataWriter, col_nbpepth, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              int protein_pep_nb =
                protein_match->getProteinXtpSp()->countTrypticPeptidesForPAI();
              rdata_append_real_value(mp_rdataWriter, protein_pep_nb);
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_nbpepth);

  // Append protein mass (Da) column
  rdata_begin_column(mp_rdataWriter, col_mass, row_count);
  for(IdentificationGroup *ident : msp_project->getIdentificationGroupList())
    {
      for(const std::pair<unsigned int, GroupingGroupSp> group_pair :
          ident->getGroupStore().getGroupMap())
        {
          for(const ProteinMatch *protein_match :
              group_pair.second.get()->getProteinMatchList())
            {
              int protein_mass = protein_match->getProteinXtpSp()->getMass();
              rdata_append_real_value(mp_rdataWriter, protein_mass);
            }
        }
    }
  rdata_end_column(mp_rdataWriter, col_mass);

  rdata_end_table(mp_rdataWriter, row_count, "Quantification info data");


  closeMCQRDataFile();
}

void
McqrRdata::writeExperimentalSummaryTable(
  const QFileInfo &experimental_summary_datafile)
{

  m_rdataFile = open(experimental_summary_datafile.absoluteFilePath().toUtf8(),
                     O_CREAT | O_WRONLY, 0664);
  mp_rdataWriter = rdata_writer_init(&write_data, RDATA_WORKSPACE);
  rdata_begin_file(mp_rdataWriter, &m_rdataFile);

  McqrExpSummary summary =
    msp_project->getMcqrExperimentSp().get()->getMcqrExpSummary();
  rdata_column_t *col_attribute =
    rdata_add_column(mp_rdataWriter, "attribute", RDATA_TYPE_STRING);
  rdata_column_t *col_value =
    rdata_add_column(mp_rdataWriter, "value", RDATA_TYPE_STRING);
  std::size_t row_number = getExperimentalSummaryRowNumber();
  qDebug() << "rows " << row_number;

  rdata_begin_table(mp_rdataWriter, "summary.data");
  rdata_begin_column(mp_rdataWriter, col_attribute, row_number);
  rdata_append_string_value(mp_rdataWriter, "Fractioning");
  if(!summary.m_fractioning)
    {
      rdata_append_string_value(mp_rdataWriter, "Fraction_name");
    }
  rdata_append_string_value(mp_rdataWriter, "Labeling");
  rdata_append_string_value(mp_rdataWriter, "Method");
  rdata_end_column(mp_rdataWriter, col_attribute);

  rdata_begin_column(mp_rdataWriter, col_value, row_number);
  rdata_append_string_value(
    mp_rdataWriter, QVariant(summary.m_fractioning).toString().toUtf8());
  if(!summary.m_fractioning)
    {
      rdata_append_string_value(mp_rdataWriter,
                                summary.m_fractionName.toUtf8());
    }
  rdata_append_string_value(
    mp_rdataWriter, QVariant(summary.m_isotopicLabeling).toString().toUtf8());
  rdata_append_string_value(mp_rdataWriter,
                            summary.m_quantificationMethod.toUtf8());
  rdata_end_column(mp_rdataWriter, col_value);
  rdata_end_table(mp_rdataWriter, row_number, "Experimental summary data");

  closeMCQRDataFile();
}

std::size_t
McqrRdata::getExperimentalSummaryRowNumber()
{
  std::size_t number_of_parameters;
  number_of_parameters = msp_project->getMcqrExperimentSp()
                           .get()
                           ->getMcqrExpSummary()
                           .m_numberOfParameters;
  // Remove one useless line
  if(msp_project->getMcqrExperimentSp()
       .get()
       ->getMcqrExpSummary()
       .m_fractioning)
    {
      number_of_parameters = number_of_parameters - 1;
    }
  return number_of_parameters;
}

QString
McqrRdata::createTheMergeRScript(const QString tmp_path,
                                 const QString final_rdata_path,
                                 const QString masschroqml_path)
{
  QFile data(tmp_path + "/merge_rdata_script.R");
  data.open(QFile::WriteOnly);
  QTextStream tstream(&data);
  Grantlee::OutputStream os(&tstream);


  Grantlee::Engine *engine_p = new Grantlee::Engine();
  auto loader = QSharedPointer<Grantlee::FileSystemTemplateLoader>::create();
  loader->setTemplateDirs({":/templates/resources/templates"});
  engine_p->addTemplateLoader(loader);

  Grantlee::Template rscript_template_sp =
    engine_p->loadByName("merge_rdata_template");
  if(!rscript_template_sp->errorString().isEmpty())
    {
      throw pappso::PappsoException(
        QObject::tr("An error happened during the template file loading :\n%1")
          .arg(rscript_template_sp->errorString()));
    }

  Grantlee::Context grantlee_context;
  grantlee_context.insert("tmp_path", tmp_path);
  grantlee_context.insert("final_path", final_rdata_path);
  grantlee_context.insert("mcqml", masschroqml_path);

  rscript_template_sp->render(&os, &grantlee_context);
  return data.fileName();
}


void
McqrRdata::mergeTheRDataFiles(const QString script_path)
{
  QSettings settings;
  QString rscript_binary_path =
    settings.value("path/rscript_binary", "Rscript").toString();
  QStringList script_path_param;
  script_path_param << script_path;

  QProcess *r_process = new QProcess();
  r_process->start(rscript_binary_path, script_path_param);

  if(!r_process->waitForStarted())
    {
      QString err =
        QObject::tr(
          "Could not start Rscript process '%1' with arguments '%2': %3")
          .arg(rscript_binary_path)
          .arg(script_path_param.join(QStringLiteral(" ")))
          .arg(r_process->errorString());
      throw pappso::PappsoException(err);
    }

  while(r_process->waitForReadyRead())
    {
    }
  qDebug() << "R merge Error: " << r_process->readAllStandardError();
  QByteArray result = r_process->readAll();

  while(r_process->waitForFinished())
    {
    }
  QProcess::ExitStatus Status = r_process->exitStatus();

  delete r_process;
  if(Status != 0)
    {
      r_process->kill();
      delete r_process;
      throw pappso::PappsoException(
        QObject::tr("error executing R process Status != 0 : %1 %2\n%3")
          .arg(rscript_binary_path)
          .arg(script_path_param.join(" ").arg(result.data())));
    }
}
