/**
 * \file /gui/run/sage/sagerundialog.cpp
 * \date 08/05/2025
 * \author Olivier Langella
 * \brief dialog window to run Sage process
 */

/*******************************************************************************
 * Copyright (c) 2025 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/>.
 *
 ******************************************************************************/

// sage -f /gorgone/pappso/moulon/database/Zea_mays.B73_RefGen_v4.pep.all.fasta
// /tmp/sage_settings.json
// /gorgone/pappso/data_extraction_pappso/mzML/20120906_balliau_extract_1_A01_urnb-1.mzML


//  ACDEFGHIKLMNPQRSTVWY

#include "sagerundialog.h"
#include "ui_sage_run_dialog.h"
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/exception/exceptionnotfound.h>
#include "../../../utils/utils.h"
#include <QJsonObject>
#include <QSettings>
#include <QFileDialog>
#include <QTreeView>
#include <QMessageBox>
#include <QJsonArray>
#include <QDesktopServices>
#include <QFileInfo>
#include <QDebug>

SageRunDialog::SageRunDialog(QWidget *parent)
  : QDialog(parent), ui(new Ui::SageRunDialog)
{
  qDebug();
  ui->setupUi(this);
  this->setModal(true);
  mpa_mzFileList = new QStringListModel();
  ui->mz_file_listview->setModel(mpa_mzFileList);

  loadJsonFile(
    QFile(":/templates/resources/templates/sage/QExactive_classic.json"));
  json2ui();


  QSettings settings;
  QString sage_bin_path =
    settings.value("path/sage_bin", "/usr/local/bin/sage").toString();
  ui->sage_bin_label->setText(sage_bin_path);
  checkSageBin();
}

SageRunDialog::~SageRunDialog()
{
  delete mpa_mzFileList;
}

void
SageRunDialog::selectSageBin()
{
  try
    {
      QSettings settings;
      QString sage_bin_path = settings.value("path/sage_bin", "").toString();


      QString filename =
        QFileDialog::getOpenFileName(this,
                                     tr("select Sage executable"),
                                     QDir(sage_bin_path).absolutePath(),
                                     tr("all files (*);;exe files (*.exe)"));
      if(!filename.isEmpty())
        {
          fillSageBinPath(filename, true);
        }
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}


void
SageRunDialog::loadJsonFile(QFile json_file)
{

  QJsonParseError parseError;

  if(!json_file.open(QIODevice::ReadOnly))
    {
      throw pappso::PappsoException(
        QObject::tr("error reading json from file %1")
          .arg(json_file.fileName()));
    }


  QByteArray jsonData = json_file.readAll();
  // ConsoleOut::mcq_cerr() << jsonData;
  m_jsonDocument = QJsonDocument::fromJson(jsonData, &parseError);

  if(parseError.error != QJsonParseError::ParseError::NoError)
    {
      throw pappso::PappsoException(
        QObject::tr("error parsing default json from stdin, at byte %2:\n%1")
          .arg(parseError.errorString())
          .arg(parseError.offset));
    }
}

void
SageRunDialog::json2ui()
{

  std::map<QString, QString> msfilepathlist;
  QString fasta_file(documentFind("database", "fasta").toString());

  ui->fasta_file_label->setText(fasta_file);


  ui->output_directory_label->setText(
    m_jsonDocument.object().value("output_directory").toString());

  QStringList mzml_list;
  for(auto element :
      m_jsonDocument.object().value("mzml_paths").toArray().toVariantList())
    {
      mzml_list << element.toString();
    }
  mpa_mzFileList->setStringList(mzml_list);

  //************database **************

  // populate the items of the list
  ui->staticModificationsListWidget->clear();
  QJsonObject static_mods_json = m_jsonDocument.object()
                                   .value("database")
                                   .toObject()
                                   .value("static_mods")
                                   .toObject();
  for(const QString &aa_mod : static_mods_json.keys())
    {
      QListWidgetItem *item_json = new QListWidgetItem();
      item_json->setText(QString("%1: %2").arg(aa_mod).arg(
        static_mods_json.value(aa_mod).toDouble()));
      item_json->setData(Qt::ItemDataRole::UserRole,
                         static_mods_json.value(aa_mod));
      ui->staticModificationsListWidget->addItem(item_json);
    }

  ui->variableModificationsListWidget->clear();
  QJsonObject var_mods_json = m_jsonDocument.object()
                                .value("database")
                                .toObject()
                                .value("variable_mods")
                                .toObject();
  for(const QString &aa_mod : var_mods_json.keys())
    {
      QStringList mass_list;
      for(auto mass_json : var_mods_json.value(aa_mod).toArray())
        {
          mass_list << QString("%1").arg(mass_json.toDouble());
        }
      QListWidgetItem *item_json = new QListWidgetItem();
      item_json->setText(
        QString("%1: [%2]").arg(aa_mod).arg(mass_list.join(", ")));
      item_json->setData(Qt::ItemDataRole::UserRole,
                         var_mods_json.value(aa_mod).toArray());
      ui->variableModificationsListWidget->addItem(item_json);
    }
  //  "database": {
  //  "bucket_size": 8192,
  // "enzyme": {
  //   "missed_cleavages": 2,
  ui->prefilter_database_checkBox->setChecked(m_jsonDocument.object()
                                                .value("database")
                                                .toObject()
                                                .value("prefilter")
                                                .toBool());
  ui->prefilter_chunck_size_database_spinBox->setValue(
    m_jsonDocument.object()
      .value("database")
      .toObject()
      .value("prefilter_chunk_size")
      .toInt());
  ui->prefilter_low_memory_database_checkBox->setChecked(
    m_jsonDocument.object()
      .value("database")
      .toObject()
      .value("prefilter_low_memory")
      .toBool());


  ui->missed_cleavages_spinbox->setValue(m_jsonDocument.object()
                                           .value("database")
                                           .toObject()
                                           .value("enzyme")
                                           .toObject()
                                           .value("missed_cleavages")
                                           .toInt());
  ui->cleave_at_edit->setText(m_jsonDocument.object()
                                .value("database")
                                .toObject()
                                .value("enzyme")
                                .toObject()
                                .value("cleave_at")
                                .toString());
  ui->restrict_edit->setText(m_jsonDocument.object()
                               .value("database")
                               .toObject()
                               .value("enzyme")
                               .toObject()
                               .value("restrict")
                               .toString());
  ui->max_length_spinbox->setValue(m_jsonDocument.object()
                                     .value("database")
                                     .toObject()
                                     .value("enzyme")
                                     .toObject()
                                     .value("max_len")
                                     .toInt());
  ui->min_length_spinbox->setValue(m_jsonDocument.object()
                                     .value("database")
                                     .toObject()
                                     .value("enzyme")
                                     .toObject()
                                     .value("min_len")
                                     .toInt());

  ui->c_terminal_checkbox->setChecked(m_jsonDocument.object()
                                        .value("database")
                                        .toObject()
                                        .value("enzyme")
                                        .toObject()
                                        .value("c_terminal")
                                        .toBool());
  ui->semi_enzymatic_checkbox->setChecked(m_jsonDocument.object()
                                            .value("database")
                                            .toObject()
                                            .value("enzyme")
                                            .toObject()
                                            .value("semi_enzymatic")
                                            .toBool());


  /*
  "precursor_tol": {
    "ppm": [
      -10.0,
      10.0
    ]
  },*/
  ui->precursor_tolerance_widget->setPrecision(getPrecisionPtrFromJson(
    m_jsonDocument.object().value("precursor_tol").toObject()));
  ui->fragment_tolerance_widget->setPrecision(getPrecisionPtrFromJson(
    m_jsonDocument.object().value("fragment_tol").toObject()));

  ui->max_fragment_charge_spinbox->setValue(
    m_jsonDocument.object().value("max_fragment_charge").toInt());
  ui->max_peaks_spinbox->setValue(
    m_jsonDocument.object().value("max_peaks").toInt());
  ui->min_matched_peaks_spinbox->setValue(
    m_jsonDocument.object().value("min_matched_peaks").toInt());
  ui->min_peaks_spinbox->setValue(
    m_jsonDocument.object().value("min_peaks").toInt());
  ui->deisotope_checkbox->setChecked(
    m_jsonDocument.object().value("deisotope").toBool());
  ui->chimera_checkbox->setChecked(
    m_jsonDocument.object().value("chimera").toBool());
  ui->wide_window_checkbox->setChecked(
    m_jsonDocument.object().value("wide_window").toBool());
  ui->predict_rt_checkbox->setChecked(
    m_jsonDocument.object().value("predict_rt").toBool());
  ui->report_psms_spinbox->setValue(
    m_jsonDocument.object().value("report_psms").toInt());

  //  "deisotope": true,
  //"chimera": false,
  //"wide_window": false,
  //"min_peaks": 15,
  //"max_peaks": 150,
  //"max_fragment_charge": 1,
  //"min_matched_peaks": 6,
  //"report_psms": 1,
  //"predict_rt": true,
}


const QJsonValue
SageRunDialog::documentFind(const QString &key1, const QString &key2) const
{
  QJsonObject obj1 = m_jsonDocument.object();
  auto it1         = obj1.find(key1);
  if(it1 != obj1.end())
    {
      QJsonObject obj2 = it1.value().toObject();
      auto it2         = obj2.find(key2);
      if(it2 != obj2.end())
        {
          return it2.value();
        }
      else
        {
          throw pappso::ExceptionNotFound(
            QObject::tr("key2 %1 not found in json document element %2")
              .arg(key2)
              .arg(key1));
        }
    }
  else
    {
      throw pappso::ExceptionNotFound(
        QObject::tr("key1 %1 not found in json document").arg(key1));
    }
}

void
SageRunDialog::loadJson()
{
  try
    {
      QSettings settings;
      QString tandem_bin_path = settings.value("path/sage", "").toString();


      QString filename =
        QFileDialog::getOpenFileName(this,
                                     tr("select Sage JSON file"),
                                     QDir(tandem_bin_path).absolutePath(),
                                     tr("all files (*);;JSON files (*.json)"));


      loadJsonFile(QFile(filename));
      json2ui();
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}


void
SageRunDialog::selectFasta()
{
  try
    {
      QSettings settings;
      QString tandem_bin_path = settings.value("path/fasta", "").toString();


      QString filename =
        QFileDialog::getOpenFileName(this,
                                     tr("select FASTA file"),
                                     QDir(tandem_bin_path).absolutePath(),
                                     tr("all files (*);;FASTA files (*.fas)"));

      ui->fasta_file_label->setText(filename);
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}

void
SageRunDialog::saveJson()
{
  try
    {
      QSettings settings;
      QString tandem_bin_path = settings.value("path/fasta", "").toString();


      QString filename = QFileDialog::getSaveFileName(
        this,
        tr("Save Sage JSON file"),
        tr("%1/sage_settings.json").arg(tandem_bin_path),
        tr("Sage JSON (*.json)"));

      if(filename.isEmpty())
        {
          return;
        }
      else
        {
          ui2json();

          qDebug() << "open json file " << filename;
          QFile jsonf(filename);
          jsonf.open(QIODevice::WriteOnly);
          if(jsonf.error() != QFileDevice::FileError::NoError)
            {
              throw pappso::PappsoException(
                QObject::tr("Unable to write JSON output file %1")
                  .arg(filename));
            }
          jsonf.write(m_jsonDocument.toJson());
          jsonf.close();
        }
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}


QString
SageRunDialog::urlizeFilePath(bool use_url, const QString &file_path) const
{

  if(use_url)
    // since sage 0.15beta2
    return QUrl::fromLocalFile(file_path).toString();
  return file_path;
}

void
SageRunDialog::ui2json()
{
  bool use_url = getSageRunBatch().useQurl();
  qWarning() << "getSageRunBatch().sageVersion "
             << getSageRunBatch().sageVersion;
  qWarning() << "getSageRunBatch().useQurl() " << use_url;
  QJsonObject database = m_jsonDocument.object().value("database").toObject();
  // QUrl::fromLocalFile(QFileInfo(jsonf).absoluteFilePath()).toString()
  database.insert(
    "fasta", QJsonValue(urlizeFilePath(use_url, ui->fasta_file_label->text())));


  // "static_mods": {
  // "C": 57.021465
  // },
  QJsonObject static_mod_json;
  for(int i = 0; i < ui->staticModificationsListWidget->count(); ++i)
    {
      QString key =
        ui->staticModificationsListWidget->item(i)->text().split(":").first();
      static_mod_json.insert(key,
                             ui->staticModificationsListWidget->item(i)
                               ->data(Qt::ItemDataRole::UserRole)
                               .toJsonValue());
    }
  database.insert("static_mods", static_mod_json);

  /*
  "variable_mods": {
    "^Q": [-17.026548],
    "[": [42.0106],
    "^E": [-18.010565],
    "M": [15.994915]
  },*/

  QJsonObject variable_mod_json;
  for(int i = 0; i < ui->variableModificationsListWidget->count(); ++i)
    {
      QString key =
        ui->variableModificationsListWidget->item(i)->text().split(":").first();
      variable_mod_json.insert(key,
                               ui->variableModificationsListWidget->item(i)
                                 ->data(Qt::ItemDataRole::UserRole)
                                 .toJsonArray());
    }
  database.insert("variable_mods", variable_mod_json);

  // prefilter database
  //"database": {
  //   "prefilter": true,

  database.insert("prefilter",
                  QJsonValue(ui->prefilter_database_checkBox->isChecked()));
  database.insert(
    "prefilter_chunk_size",
    QJsonValue(ui->prefilter_chunck_size_database_spinBox->value()));
  database.insert(
    "prefilter_low_memory",
    QJsonValue(ui->prefilter_low_memory_database_checkBox->isChecked()));
  //   "prefilter_chunk_size": 1000,
  // "prefilter_low_memory": false,


  QJsonObject enzyme = database.value("enzyme").toObject();
  enzyme.insert("missed_cleavages",
                QJsonValue(ui->missed_cleavages_spinbox->value()));
  enzyme.insert("cleave_at", QJsonValue(ui->cleave_at_edit->text()));
  enzyme.insert("max_len", QJsonValue(ui->max_length_spinbox->value()));
  enzyme.insert("min_len", QJsonValue(ui->min_length_spinbox->value()));
  if(ui->restrict_edit->text().isEmpty())
    {
      enzyme.insert("restrict", QJsonValue());
    }
  else
    {
      enzyme.insert("restrict", QJsonValue(ui->restrict_edit->text()));
    }
  enzyme.insert("c_terminal", QJsonValue(ui->c_terminal_checkbox->isChecked()));
  enzyme.insert("semi_enzymatic",
                QJsonValue(ui->semi_enzymatic_checkbox->isChecked()));
  database.insert("enzyme", enzyme);


  QJsonObject jo = m_jsonDocument.object();
  jo.insert("database", database);
  jo.insert(
    "output_directory",
    QJsonValue(urlizeFilePath(use_url, ui->output_directory_label->text())));
  jo.insert("max_fragment_charge",
            QJsonValue(ui->max_fragment_charge_spinbox->value()));
  jo.insert("max_peaks", QJsonValue(ui->max_peaks_spinbox->value()));
  jo.insert("min_matched_peaks",
            QJsonValue(ui->min_matched_peaks_spinbox->value()));
  jo.insert("min_peaks", QJsonValue(ui->min_peaks_spinbox->value()));
  jo.insert("deisotope", QJsonValue(ui->deisotope_checkbox->isChecked()));
  jo.insert("chimera", QJsonValue(ui->chimera_checkbox->isChecked()));
  jo.insert("wide_window", QJsonValue(ui->wide_window_checkbox->isChecked()));
  jo.insert("predict_rt", QJsonValue(ui->predict_rt_checkbox->isChecked()));

  jo.insert("report_psms", QJsonValue(ui->report_psms_spinbox->value()));

  //  "mzml_paths": [],
  QStringList urlizeFilePathList;
  for(const QString &mz_file : mpa_mzFileList->stringList())
    {
      QString urlized = urlizeFilePath(use_url, mz_file);
      if(urlized.endsWith("/analysis.tdf"))
        {
          urlized = QFileInfo(mz_file).absoluteDir().absolutePath();
          // urlized = urlized.replace("/analysis.tdf", "");
        }
      urlizeFilePathList << urlized;
    }
  jo.insert("mzml_paths", QJsonArray::fromStringList(urlizeFilePathList));


  jo.insert(
    "precursor_tol",
    getJsonPrecisionPtr(ui->precursor_tolerance_widget->getPrecision()));

  jo.insert("fragment_tol",
            getJsonPrecisionPtr(ui->fragment_tolerance_widget->getPrecision()));


  m_jsonDocument.setObject(jo);
}


void
SageRunDialog::selectOutputDirectory()
{
  try
    {
      QSettings settings;
      QString default_output_location =
        settings.value("path/identificationfiles", "").toString();

      QString directory = QFileDialog::getExistingDirectory(
        this, tr("Choose output directory"), default_output_location);

      if(!directory.isEmpty())
        {
          settings.setValue("path/identificationfiles", directory);
          ui->output_directory_label->setText(directory);
        }
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}


void
SageRunDialog::selectMzFiles()
{
  try
    {
      QSettings settings;
      QString default_mz_location =
        settings.value("path/tandemrun_mzfiles_directory", "").toString();

      QStringList filenames = QFileDialog::getOpenFileNames(
        this,
        tr("select peak list files"),
        default_mz_location,
        tr("any mz files (*.mzXML *.mzxml *.mzML *.mzml *.mgf *.tdf);;mzXML "
           "(*.mzXML "
           "*.mzxml);;mzML (*.mzML *.mzml);;MGF (*.mgf);; tdf (*.tdf);;all "
           "files (*)"));

      if(filenames.size() > 0)
        {
          settings.setValue("path/tandemrun_mzfiles_directory",
                            QFileInfo(filenames[0]).absolutePath());
        }
      QStringList file_list = mpa_mzFileList->stringList();
      file_list.append(filenames);
      mpa_mzFileList->setStringList(file_list);
    }
  catch(pappso::PappsoException &error)
    {
      // QMessageBox::warning(this,
      //                  tr("Error choosing identification result files :
      //                  %1").arg(error.qwhat()), error);
    }
}

void
SageRunDialog::selectTdfFolder()
{
  try
    {
      // Input select folders
      QSettings settings;
      QString default_tdf_location =
        settings.value("path/tandemrun_tdf_directory", "/").toString();
      QFileDialog directories_dialog;
      directories_dialog.setDirectory(default_tdf_location);
      directories_dialog.setFileMode(QFileDialog::Directory);
      directories_dialog.setOption(QFileDialog::DontUseNativeDialog, true);
      directories_dialog.setWindowTitle("Select the timsTOF folders");
      QListView *lView = directories_dialog.findChild<QListView *>("listView");
      if(lView)
        lView->setSelectionMode(QAbstractItemView::MultiSelection);
      QTreeView *tView = directories_dialog.findChild<QTreeView *>();
      if(tView)
        tView->setSelectionMode(QAbstractItemView::MultiSelection);
      directories_dialog.exec();

      QStringList directories_names;
      if(directories_dialog.result() == QDialog::Accepted)
        {
          directories_names = directories_dialog.selectedFiles();
        }

      for(QString dirnames : directories_names)
        {
          qDebug() << dirnames;
        }
      if(directories_names.size() > 1)
        {
          settings.setValue("path/tandemrun_tdf_directory",
                            QFileInfo(directories_names[0]).absolutePath());
          directories_names.pop_front();
        }

      // Input select wich type between mgf and TDF
      QMessageBox msgBox;
      QPushButton *mgf_button =
        msgBox.addButton(tr("MGF file"), QMessageBox::ActionRole);
      QPushButton *tdf_button =
        msgBox.addButton(tr("TDF file"), QMessageBox::ActionRole);
      msgBox.addButton(QMessageBox::Discard);

      msgBox.setText("Which file do you want to use ?");
      msgBox.setInformativeText("Choose between MGF and TDF format");
      msgBox.setDefaultButton(QMessageBox::Discard);
      msgBox.exec();

      if(msgBox.clickedButton() == mgf_button)
        {
          // Use the MGF file for identification
          for(QString &directory_name : directories_names)
            {
              qDebug() << directory_name;
              QFileInfoList files = QDir(directory_name).entryInfoList();
              QStringList results;
              for(QFileInfo file : files)
                {
                  if(Utils::guessDataFileFormatFromFile(
                       file.absoluteFilePath()) ==
                     pappso::Enums::MsDataFormat::MGF)
                    {
                      results.append(file.absoluteFilePath());
                    }
                }
              qDebug() << results;

              if(results.isEmpty())
                {
                  throw pappso::PappsoException(
                    tr("The directory %1/ does not contain the mandatory "
                       "mgf file")
                      .arg(directory_name));
                }
              else if(results.size() > 1)
                {
                  throw pappso::PappsoException(
                    tr("The directory %1/ contains multiple mgf files\nPlease "
                       "correct the ambiguous situation\n")
                      .arg(directory_name));
                }
              else
                {
                  directory_name = results[0];
                }
            }

          QStringList file_list = mpa_mzFileList->stringList();
          file_list.append(directories_names);
          mpa_mzFileList->setStringList(file_list);
        }
      else if(msgBox.clickedButton() == tdf_button)
        {
          // Use analysis.tdf file for identification
          for(QString &directory_name : directories_names)
            {
              qDebug() << directory_name;
              directory_name = directory_name + "/analysis.tdf";
              if(!QFileInfo(directory_name).exists())
                {
                  throw pappso::PappsoException(
                    tr("The directory %1/ does not contain the mandatory "
                       "analysis.tdf file")
                      .arg(directory_name));
                }
            }

          QStringList file_list = mpa_mzFileList->stringList();
          file_list.append(directories_names);
          mpa_mzFileList->setStringList(file_list);
        }
    }
  catch(pappso::PappsoException &error)
    {
      QMessageBox::warning(
        this, tr("Error choosing identification result files"), error.qwhat());
    }
}


void
SageRunDialog::clearMzFiles()
{
  mpa_mzFileList->removeRows(0, mpa_mzFileList->rowCount());
}

pappso::PrecisionPtr
SageRunDialog::getPrecisionPtrFromJson(const QJsonObject &precision_json)
{
  /*"ppm": [
      -10.0,
      10.0
    ]
    "da": [
      -0.02,
      0.02
    ]*/
  pappso::PrecisionPtr precision = pappso::PrecisionFactory::getPpmInstance(50);
  if(precision_json.value("ppm").isArray())
    {
      precision = pappso::PrecisionFactory::getPpmInstance(
        precision_json.value("ppm").toArray().at(1).toDouble());
    }

  if(precision_json.value("da").isArray())
    {
      precision = pappso::PrecisionFactory::getDaltonInstance(
        precision_json.value("da").toArray().at(1).toDouble());
    }

  return precision;
}

QJsonObject
SageRunDialog::getJsonPrecisionPtr(pappso::PrecisionPtr precision_ptr)
{
  QJsonObject precision_json;
  QJsonArray arr_val;
  arr_val.push_back(QJsonValue(precision_ptr->getNominal() * -1));
  arr_val.push_back(QJsonValue(precision_ptr->getNominal()));
  if(precision_ptr->unit() == pappso::Enums::PrecisionUnit::dalton)
    {
      precision_json.insert("da", arr_val);
    }
  if(precision_ptr->unit() == pappso::Enums::PrecisionUnit::ppm)
    {
      precision_json.insert("ppm", arr_val);
    }

  return precision_json;
}


void
SageRunDialog::done(int r)
{

  if(QDialog::Accepted == r) // ok was pressed
    {

      QSettings settings;
      settings.setValue("sage/use_slurm", "false");
      if(ui->use_htcondor_groupbox->isChecked())
        {
          settings.setValue("sage/use_slurm", "true");
        }
      // ui->sage_bin_label->setText(filename);
      settings.setValue("path/sage_bin", ui->sage_bin_label->text());


      // QString condor_tmp_dir =
      // QString("%1/i2masschroq").arg(settings.value("condor/tmp_dir",
      // "/tmp").toString()); _p_tmp_dir = new QTemporaryDir(condor_tmp_dir);
      //_p_tmp_dir->setAutoRemove(settings.value("condor/tmp_dir_autoremove",
      // true).toBool()); _condor_submit_command =
      // settings.value("condor/submit", "/usr/bin/condor_submit").toString();
      //_condor_q_command = settings.value("condor/condor_q",
      //"/usr/bin/condor_q").toString(); _condor_rm_command =
      // settings.value("condor/condor_rm", "/usr/bin/condor_rm").toString();
      settings.setValue("sage/sage_request_memory",
                        ui->request_memory_edit->text());

      if(checkBeforeRun())
        {
          QDialog::done(r);
        }
      else
        {
          QDialog::reject();
        }
      return;
    }
  else // cancel, close or exc was pressed
    {
      QDialog::done(r);
      return;
    }
}

bool
SageRunDialog::checkBeforeRun()
{
  ui2json();

  return true;
}

SageRunBatch
SageRunDialog::getSageRunBatch() const
{
  SageRunBatch run_batch;

  run_batch.sageJsonDocument = m_jsonDocument;
  run_batch.useSlurm         = ui->use_htcondor_groupbox->isChecked();
  run_batch.sageThreads      = ui->thread_spin_box->value();
  run_batch.sageSlurmMemory  = ui->request_memory_edit->text();
  run_batch.sageBin          = ui->sage_bin_label->text();
  run_batch.sageVersion      = ui->sage_version_label->text();
  run_batch.sageFastaFile =
    QFileInfo(ui->fasta_file_label->text()).absoluteFilePath();
  run_batch.sageOutputDir = ui->output_directory_label->text();
  if(mpa_mzFileList != nullptr)
    {
      run_batch.sageMzFileList = mpa_mzFileList->stringList();
    }

  return run_batch;
}


void
SageRunDialog::fillSageBinPath(const QString &sage_bin_path_in,
                               bool popup_firefox)
{
  qDebug() << sage_bin_path_in;
  QSettings settings;
  if(sage_bin_path_in.isEmpty())
    {
      // try to find default X!Tandem, depending on platform
      ui->sage_bin_label->setText("");
      qDebug();

      QFileInfo file(QCoreApplication::applicationDirPath() + "/sage.exe");
      if(file.exists())
        { // for Windows
          fillSageBinPath(file.absoluteFilePath(), false);
        }
      else if(QFileInfo("/usr/bin/sage").exists())
        {
          fillSageBinPath("/usr/bin/sage", false);
        }
      else if(QFileInfo("/usr/local/bin/sage").exists())
        {
          fillSageBinPath("/usr/local/bin/sage", false);
        }
      else
        {
          ui->sage_version_label->setText(
            "<font color=\"red\">Please select the sage.exe file "
            "path</font>");
          ui->a1_exe_groupbox->setChecked(true);
        }
    }
  else
    {
      qDebug();
      QFileInfo sage_bin(sage_bin_path_in);
      QString sage_bin_path = sage_bin.absoluteFilePath();

      if(!sage_bin.exists())
        {
          QMessageBox::warning(
            this,
            tr("Sage binary file not found"),
            tr("%1 check sage binary file path.").arg(sage_bin_path));
        }

      else
        {
          if(sage_bin.isExecutable())
            {
              qDebug();
              ui->sage_bin_label->setText(sage_bin_path);
              settings.setValue("path/sage_bin", sage_bin_path);
              checkSageBin();
            }
          else
            {
              if(popup_firefox)
                {
                  QDesktopServices::openUrl(
                    QUrl("https://github.com/lazear/sage"));
                }
              QMessageBox::warning(
                this,
                tr("Wrong sage.exe file"),
                tr("%1 is not executable.").arg(sage_bin_path));
            }
        }
    }
  qDebug();
}


bool
SageRunDialog::checkSageBin()
{
  QString sage_bin_path = ui->sage_bin_label->text();

  qDebug() << sage_bin_path;
  QString sage_install_text =
    "Please check that Sage is "
    "installed on your computer.\nIt is available at "
    ":\nhttps://github.com/lazear/sage\nOnce it is installed, "
    "please "
    "set the correct path to the sage.exe file";
  QFileInfo sage_bin(sage_bin_path);
  if(sage_bin_path.isEmpty() || !sage_bin.exists())
    {
      QMessageBox::warning(
        this,
        tr("Wrong Sage configuration"),
        tr("sage.exe file is not set.\n%1").arg(sage_install_text));

      QDesktopServices::openUrl(QUrl("https://github.com/lazear/sage"));
    }
  else
    {

      if(sage_bin.isExecutable())
        {
          try
            {
              QString sage_version = Utils::checkSageVersion(sage_bin_path);
              if(sage_version.isEmpty())
                {
                  ui->sage_version_label->setText("Sage not found");
                }
              else
                {
                  ui->sage_version_label->setText(
                    Utils::checkSageVersion(sage_bin_path));
                }

              return true;
            }

          catch(pappso::PappsoException &error)
            {
              QMessageBox::warning(
                this,
                tr("Wrong Sage exe file"),
                tr("%1 does not seem to be a valid Sage version.\n%2")
                  .arg(sage_bin.absoluteFilePath())
                  .arg(sage_install_text));

              QDesktopServices::openUrl(QUrl("https://github.com/lazear/sage"));
            }
        }
      else
        {
          QMessageBox::warning(this,
                               tr("Wrong Sage exe file"),
                               tr("%1 is not executable.\n%2")
                                 .arg(sage_bin_path)
                                 .arg(sage_install_text));
        }
    }


  return false;
}
