/**
 * \file /gui/run/msstats/msstatsrunview.cpp
 * \date 25/05/2023
 * \author Olivier Langella
 * \brief dialog window to run MSstats 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 "msstatsrunview.h"
#include "../../mainwindow.h"
#include "ui_msstats_run_view.h"
#include <QDebug>
#include <odsstream/odsdocwriter.h>
#include <odsstream/odsexception.h>
#include <odsstream/tsvreader.h>
#include "../../../output/mcqr/mcqrmetadataods.h"
#include "../../../input/msstats/msstatstsvtranslator.h"
#include <pappsomspp/core/exception/exceptionnotpossible.h>
#include <pappsomspp/core/processing/uimonitor/uimonitorvoid.h>


MsStatsRunView::MsStatsRunView(MainWindow *parent)
  : RworkflowRunViewBase(parent), ui(new Ui::MsStatsRunView)
{
  ui->setupUi(this);


  qDebug();
  m_rviewName = "MSstats";
  checkInstall();
}

MsStatsRunView::~MsStatsRunView()
{
}

WidgetRprocess *
MsStatsRunView::getWidgetRprocess() const
{
  return ui->widgetRprocess;
}

void
MsStatsRunView::checkInstall()
{

  Cutelee::Engine *engine_p = new Cutelee::Engine();
  auto loader = std::shared_ptr<Cutelee::FileSystemTemplateLoader>(
    new Cutelee::FileSystemTemplateLoader());
  loader->setTemplateDirs({":/templates/resources/templates/mcqr_scripts"});
  engine_p->addTemplateLoader(loader);
  Cutelee::Template rscript_template_sp =
    engine_p->loadByName("mcqr_packages_handler.R");
  Cutelee::Context empty_context;
  ui->widgetRprocess->executeOnTheRecord(
    rscript_template_sp->render(&empty_context));


  loader->setTemplateDirs({":/templates/resources/templates/r_scripts"});
  engine_p->addTemplateLoader(loader);
  rscript_template_sp = engine_p->loadByName("msstatsinstall.R");
  ui->widgetRprocess->executeOnTheRecord(
    rscript_template_sp->render(&empty_context));


  executeStep("libraries");
}
/*
void
MsStatsRunView::doSelectMasschroqMlFile()
{

  try
    {
      QSettings settings;

      QString default_location = settings.value("path/mcqfile", "").toString();

      QString filename = QFileDialog::getOpenFileName(
        this,
        tr("select masschroqML file"),
        QDir(default_location).absolutePath(),
        tr("masschroqML files (*.masschroqml);;all files (*)"));


      if(!filename.isEmpty())
        {
          settings.setValue("path/mcqfile", QFileInfo(filename).absolutePath());

          if(m_mcqlReader.readFile(filename))
            {
              executeStep("load");
            }
          else
            {

              throw pappso::PappsoException(m_mcqlReader.errorString());
            }
        }
      qDebug() << filename;
    }
  catch(pappso::PappsoException &error)
    {
      warning(
        tr("Error reading masschroqML parameter file : %1").arg(error.qwhat()));
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}
*/
void
MsStatsRunView::doMcqrDubiousDataFilter()
{
  executeStep("mcqr_dubiousDataFilter");
}

void
MsStatsRunView::setWorkingDirectoryLabel()
{
  m_mcqCborReader.setMcqrWorkingDirectory(m_workingDirectory);
  ui->wdLabel->setText(m_workingDirectory);
}


void
MsStatsRunView::executeStep(const QString &step)
{

  Cutelee::Engine *engine_p = new Cutelee::Engine();
  auto loader = std::shared_ptr<Cutelee::FileSystemTemplateLoader>(
    new Cutelee::FileSystemTemplateLoader());
  loader->setTemplateDirs({":/templates/resources/templates/msstats"});
  engine_p->addTemplateLoader(loader);
  Cutelee::Template rscript_template_sp =
    engine_p->loadByName("msstats_analysis.R");
  Cutelee::Context context;
  context.insert("step", step);

  if(step != "libraries")
    {
      if(m_workingDirectory.isEmpty())
        {
          warning("Error : working directory is not set.");
          return;
        }
      else
        {

          if(ui->widgetRprocess->isFinished())
            {
              executeStep("libraries");
            }
          context.insert(
            "tmp_path",
            QDir(m_workingDirectory).absoluteFilePath(" ").trimmed());
          if(step == "load")
            {
              if(m_mcqCborReader.getMcqrMetadataSet()
                   .getMcqrMetadataList()
                   .size() == 0)
                {
                  warning("Error : masschroqML file not selected.");
                  return;
                }

              context.insert("protein_tsv_file",
                             m_mcqCborReader.getProteinTsvResultFilename());

              context.insert("peptide_tsv_file",
                             m_mcqCborReader.getPeptideTsvResultFilename(
                               m_mcqCborReader.getSingleGroupId()));
            }
          else if(step == "merge_metadata")
            {
              if(!fileExists("xicraw_nometadata.rdata"))
                {
                  warning("Error : masschroqML file not selected.");
                  return;
                }
            }

          else if(step == "mcqr_dubiousDataFilter")
            {

              context.insert("cutoff_rt", ui->rt_cutoff_spin->value());
              context.insert("cutoff_peaks", ui->peaks_cutoff_spin->value());

              if(!fileExists("xicraw.rdata"))
                {
                  warning("Error : metadata file not uploaded.");
                  return;
                }
            }
          else if(step == "msstats_dataProcess")
            {

              context.insert(
                "dataprocess_logtrans",
                ui->logtransComboBox->currentText().replace("log", ""));

              if(!fileExists("xicraw.rdata"))
                {
                  warning("Error : metadata file not uploaded.");
                  return;
                }
            }
          else if(step == "msstats_sampleQuantification")
            {
              if(!fileExists("quantData_msstats.rdata"))
                {
                  warning("Error : MSstats data process required.");
                  return;
                }
            }
          else if(step == "msstats_groupQuantification")
            {
              if(!fileExists("quantData_msstats.rdata"))
                {
                  warning("Error : MSstats data process required.");
                  return;
                }
            }
          else
            {
              throw pappso::PappsoException(
                tr("MSstats step %1 does not exists").arg(step));
            }
        }
    }

  try
    {
      ui->widgetRprocess->executeStepOnTheRecord(
        step, rscript_template_sp->render(&context));
    }
  catch(pappso::ExceptionNotPossible &error)
    {
      warning(error.qwhat());
    }
}

void
MsStatsRunView::doMsstatsDataProcess()
{

  executeStep("msstats_dataProcess");
}


void
MsStatsRunView::doGetMetadataTemplateFile()
{

  if(m_mcqCborReader.isOk() == false)
    {
      warning("Error : select your MassChroQ CBOR file before proceeding.");
      return;
    }
  QString group_id             = m_mcqCborReader.getSingleGroupId();
  McqrMetadataSet metadata_set = m_mcqCborReader.getMcqrMetadataSet();

  metadata_set.addColumn("Condition");
  metadata_set.addColumn("BioReplicate");


  QSettings settings;
  QString metadata_template_path = QFileDialog::getSaveFileName(
    this,
    tr("Save the template"),
    settings.value("mcqr/metadata_path", "metadata_template.ods").toString(),
    tr("Spreadsheet (*.ods);;All files (*.*)"));
  if(!metadata_template_path.isEmpty())
    {
      try
        {
          qDebug() << metadata_template_path;
          CalcWriterInterface *p_writer =
            new OdsDocWriter(metadata_template_path);
          qDebug();
          McqrMetadataOds mcqr_metadata_ods(p_writer, metadata_set);

          qDebug();
          p_writer->close();
          settings.setValue("mcqr/metadata_path", metadata_template_path);


          launchDesktopSoftwareOnFile(metadata_template_path);
          qDebug();
        }
      catch(OdsException &error)
        {
          qDebug() << tr("error while writing metadata template:\n%1")
                        .arg(error.qwhat());
        }
      catch(pappso::PappsoException &error)
        {
          qDebug() << tr("error while downloading the metadata template:\n%1")
                        .arg(error.qwhat());
        }
    }
}

void
MsStatsRunView::doUploadMetadataFile()
{

  QSettings settings;

  QString metadata_path = QFileDialog::getOpenFileName(
    this,
    tr("select the metadata file"),
    settings.value("mcqr/metadata_path", "/").toString(),
    tr("Spreadsheet (*.ods)"));

  if(!metadata_path.isEmpty())
    {
      try
        {
          QDir directory(m_workingDirectory);
          if(QFileInfo(directory.absoluteFilePath("metadata.ods")).exists())
            {
              if(QFile::remove(directory.absoluteFilePath("metadata.ods")))
                {
                  // OK
                }
              else
                {
                  throw pappso::PappsoException(
                    QObject::tr("Unable to remove existing file : %1\n Please "
                                "check for file system permissions")
                      .arg(directory.absoluteFilePath("metadata.ods")));
                }
            }
          if(QFile::copy(metadata_path,
                         directory.absoluteFilePath("metadata.ods")))
            {
              // OK
            }
          else
            {
              throw pappso::PappsoException(
                QObject::tr("Unable write file : %1\nPlease check for file "
                            "system permissions")
                  .arg(directory.absoluteFilePath("metadata.ods")));
            }

          executeStep("merge_metadata");
        }
      catch(pappso::PappsoException &error)
        {
          throw pappso::PappsoException(
            QObject::tr("Cannot load metadata odf file: %1")
              .arg(error.qwhat()));
        }
      qDebug();
    }
}

void
MsStatsRunView::doMsstatsSampleQuantification()
{
  executeStep("msstats_sampleQuantification");
}
void
MsStatsRunView::doMsstatsGroupQuantification()
{
  executeStep("msstats_groupQuantification");
}


void
MsStatsRunView::doGetOdsGroupQuantification()
{
  QString tsv_file = "groupQuantification.tsv";
  if(!fileExists(tsv_file))
    {
      warning("Error : MSstats group quantification required.");
      return;
    }


  QSettings settings;
  QString ods_export = QFileDialog::getSaveFileName(
    this,
    tr("Save protein abundance table"),
    settings.value("path/export_ods", "").toString(),
    tr("Spreadsheet (*.ods);;All files (*.*)"));
  if(!ods_export.isEmpty())
    {
      try
        {
          qDebug() << ods_export;
          CalcWriterInterface *p_writer = new OdsDocWriter(ods_export);
          qDebug();
          MsstatsTsvTranslator tsv_translator(p_writer);

          QFile file(filePath(tsv_file));

          TsvReader reader(tsv_translator);

          reader.parse(file);
          qDebug();
          tsv_translator.endDocument();
          p_writer->close();
          launchDesktopSoftwareOnFile(ods_export);
          qDebug();
        }
      catch(OdsException &error)
        {
          qDebug() << tr("error while writing protein abundance table:\n%1")
                        .arg(error.qwhat());
        }
      catch(pappso::PappsoException &error)
        {
          qDebug() << tr("error while downloading protein abundance table:\n%1")
                        .arg(error.qwhat());
        }
    }
}

void
MsStatsRunView::doGetOdsSampleQuantification()
{

  QString tsv_file = "sampleQuantification.tsv";
  if(!fileExists(tsv_file))
    {
      warning("Error : MSstats sample quantification required.");
      return;
    }


  QSettings settings;
  QString ods_export = QFileDialog::getSaveFileName(
    this,
    tr("Save protein abundance table"),
    settings.value("path/export_ods", "").toString(),
    tr("Spreadsheet (*.ods);;All files (*.*)"));
  if(!ods_export.isEmpty())
    {
      try
        {
          qDebug() << ods_export;
          CalcWriterInterface *p_writer = new OdsDocWriter(ods_export);
          qDebug();
          MsstatsTsvTranslator tsv_translator(p_writer);

          QFile file(filePath(tsv_file));

          TsvReader reader(tsv_translator);

          reader.parse(file);
          qDebug();
          p_writer->close();
          qDebug();

          launchDesktopSoftwareOnFile(ods_export);
        }
      catch(OdsException &error)
        {
          qDebug() << tr("error while writing protein abundance table:\n%1")
                        .arg(error.qwhat());
        }
      catch(pappso::PappsoException &error)
        {
          qDebug() << tr("error while downloading protein abundance table:\n%1")
                        .arg(error.qwhat());
        }
    }
}

void
MsStatsRunView::doGetMsstatsInputTable()
{
  QString tsv_file = "msstats.tsv";
  if(!fileExists(tsv_file))
    {
      warning("Error : MSstats data process required.");
      return;
    }


  QSettings settings;
  QString ods_export = QFileDialog::getSaveFileName(
    this,
    tr("Save MSstats input table"),
    settings.value("path/export_ods", "").toString(),
    tr("Spreadsheet (*.ods);;All files (*.*)"));
  if(!ods_export.isEmpty())
    {
      try
        {
          qDebug() << ods_export;
          CalcWriterInterface *p_writer = new OdsDocWriter(ods_export);
          qDebug();
          MsstatsTsvTranslator tsv_translator(p_writer);

          QFile file(filePath(tsv_file));

          TsvReader reader(tsv_translator);

          reader.parse(file);
          qDebug();
          p_writer->close();
          qDebug();
        }
      catch(OdsException &error)
        {
          qDebug() << tr("error while writing MSstats input table:\n%1")
                        .arg(error.qwhat());
        }
      catch(pappso::PappsoException &error)
        {
          qDebug() << tr("error while downloading MSstats input table:\n%1")
                        .arg(error.qwhat());
        }
    }
}


void
MsStatsRunView::doSelectMasschroqCborFile()
{

  try
    {
      QSettings settings;

      QString default_location = settings.value("path/mcqfile", "").toString();

      QString filename = QFileDialog::getOpenFileName(
        this,
        tr("select MassChroQ CBOR file"),
        QDir(default_location).absolutePath(),
        tr("MassChroQ CBOR files (*.cbor);;all files (*)"));


      if(!filename.isEmpty())
        {
          settings.setValue("path/mcqfile", QFileInfo(filename).absolutePath());

          pappso::UiMonitorVoid monitor;
          QFile f(filename);
          if(f.open(QIODevice::ReadOnly))
            {
              qDebug();
              m_mcqCborReader.readCbor(&f, monitor);
            }
          else
            {

              throw pappso::PappsoException(
                QObject::tr("failure opening file %1")
                  .arg(QFileInfo(filename).absolutePath()));
            }

          m_mcqCborReader.writePeptideProteinFiles(filename, monitor);
          //m_projectParameters = m_mcqCborReader.getProjectParameters();
          executeStep("load");
          qDebug() << filename;
        }
    }
  catch(pappso::PappsoException &error)
    {
      warning(tr("Error reading MassChroQ CBOR file : %1").arg(error.qwhat()));
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}
