/**
 * \file gui/mcqr_param_dialog/mcqrparamallquantidialog.cpp
 * \date 11/01/2021
 * \author Thomas Renne
 * \brief set MCQR params and run
 */

/*******************************************************************************
 * 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/>.
 *
 ******************************************************************************/

#include "ui_mcqr_param_all_quanti_dialog.h"
#include "mcqrparamallquantidialog.h"
#include <odsstream/odsdocwriter.h>
#include "../mainwindow.h"
#include "../../output/ods/mcqrmetadatasheet.h"
#include "../../input/metadataodshandler.h"
#include "../../utils/utils.h"

McqrParamAllQuantiDialog::McqrParamAllQuantiDialog(MainWindow *parent,
                                                   ProjectSp project,
                                                   QString masschroqml_name)
  : McqrParamAllQuantiDialog(parent, project)
{
  qDebug() << masschroqml_name;
  msp_mcqMsrunAlignementGroup = checkMasschroqmlPath(masschroqml_name);
  if(msp_mcqMsrunAlignementGroup.get() != nullptr)
    {
      ui->masschroqml_label->setText(
        QObject::tr("%1 masschroqml found / Group %2 selected")
          .arg(
            QFileInfo(msp_mcqMsrunAlignementGroup.get()->getMassChroqmlPath())
              .baseName())
          .arg(
            msp_mcqMsrunAlignementGroup.get()->getMsRunAlignmentGroupName()));
      m_masschroqUsed = true;

      project.get()
        ->getMcqrExperimentSp()
        .get()
        ->setAlignmentGroupLinkedToExperiment(msp_mcqMsrunAlignementGroup);
    }
  else
    {
      throw pappso::PappsoException(
        tr("Error: the masschroqml file named %1 cannot be found")
          .arg(masschroqml_name));
    }
}

McqrParamAllQuantiDialog::McqrParamAllQuantiDialog(MainWindow *parent,
                                                   ProjectSp project)
  : QDialog(parent), ui(new Ui::McqrParamAllQuantiDialog)
{
  msp_mcqMsrunAlignementGroup = nullptr;
  mp_main                     = parent;
  msp_project                 = project;

  ui->setupUi(this);
  setWindowIcon(QIcon(":/xtpcpp_icon/resources/xtandempipeline_icon.svg"));

  // Set Window title based on project name
  if(msp_project != nullptr)
    {
      setWindowTitle(QString("%1 - MCQR parameters window")
                       .arg(msp_project->getProjectName()));
    }

  // Create new McqrExperiment
  McqrExperimentSp mcqr_exp = std::make_shared<McqrExperiment>();
  msp_project->setMcqrExperimentSp(mcqr_exp);

  // Check if the masschroqml file exist
  ui->masschroqml_label->setText(
    tr("No masschroqml found, will perform SC analysis"));
  m_masschroqUsed = false;

  // Hide and keep space of the Metadata TableView
  QSizePolicy sp_retain = ui->metadata_View->sizePolicy();
  sp_retain.setRetainSizeWhenHidden(true);
  ui->metadata_View->setSizePolicy(sp_retain);
  ui->metadata_View->setVisible(false);

  connect(ui->fraction_switch,
          &pappso::SwitchWidget::clicked,
          this,
          &McqrParamAllQuantiDialog::handleFractionNameEnabling);
  connect(this,
          &McqrParamAllQuantiDialog::accepted,
          mp_main,
          &MainWindow::doAcceptedMcqrParamAllQuantiDialog);
}


McqrParamAllQuantiDialog::~McqrParamAllQuantiDialog()
{
  delete ui;
}

void
McqrParamAllQuantiDialog::reject()
{
  QDialog::reject();
}

void
McqrParamAllQuantiDialog::doRunMcqrWithRData()
{
  m_runMCQR = true;
  setMcqrExpSummary();
  QString error_message;
  if(ui->lineEdit->text().isEmpty())
    {
      error_message =
        "No metadata file loaded.\nPlease load a metadata file from the "
        "template given above";
    }
  if(error_message.isEmpty())
    {
      accept();
    }
  else
    {
      QMessageBox msgBox;
      msgBox.setWindowTitle(tr("Mcqr parameter problem"));
      msgBox.setText(error_message);
      msgBox.setIcon(QMessageBox::Warning);
      msgBox.exec();
      reject();
    }
}

void
McqrParamAllQuantiDialog::doSaveFullRDataFile()
{
  m_runMCQR = false;
  setMcqrExpSummary();
  QString error_message;
  if(ui->lineEdit->text().isEmpty())
    {
      error_message =
        "No metadata file loaded.\nPlease load a metadata file from the "
        "template given above";
    }
  if(error_message.isEmpty())
    {
      QDialog::accept();
      // emit operateWriteRDataFile();
    }
  else
    {
      QMessageBox msgBox;
      msgBox.setWindowTitle(tr("Mcqr parameter problem"));
      msgBox.setText(error_message);
      msgBox.setIcon(QMessageBox::Warning);
      msgBox.exec();
      reject();
    }
}


void
McqrParamAllQuantiDialog::doDownloadMetadataTemplate()
{
  QSettings settings;
  QString metadata_template_path = QFileDialog::getSaveFileName(
    this,
    tr("Save the template"),
    settings.value("mcqr/metadata_path", "untitled.ods").toString(),
    tr("Spreadsheet (*.ods)"));
  if(metadata_template_path != NULL)
    {
      try
        {
          CalcWriterInterface *p_writer = nullptr;
          p_writer = new OdsDocWriter(metadata_template_path);
          McqrLoadDataMode method_select = getMcqrLoadDataMode();
          McqrMetadataSheet(
            p_writer,
            msp_mcqMsrunAlignementGroup.get()->getMsRunsInAlignmentGroup(),
            method_select);

          p_writer->close();
          settings.setValue("mcqr/metadata_path", metadata_template_path);
        }
      catch(pappso::PappsoException &error)
        {
          qDebug() << tr("error while downloading the metadata template:%1")
                        .arg(error.qwhat());
        }
    }
}

void
McqrParamAllQuantiDialog::loadFilledMetadataOds()
{
  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
        {
          MetadataOdsHandler handler(msp_project);
          QFile ods_file(metadata_path);
          OdsDocReader metadata_reader(handler);
          metadata_reader.parse(&ods_file);
          ods_file.close();
          settings.setValue("mcqr/metadata_path", metadata_path);
          m_metadataOdsFile.setFile(metadata_path);
        }
      catch(pappso::PappsoException &error)
        {
          throw pappso::PappsoException(
            QObject::tr("Cannot load metadata odf file"));
        }
      qDebug() << "Read metadata finished";
      setMetadataModelView();
      ui->lineEdit->setText(metadata_path);
      qDebug();
    }
}

void
McqrParamAllQuantiDialog::setMetadataModelView()
{
  qDebug();
  std::vector<McqrMetadata *> metadata_lines =
    msp_project->getMcqrExperimentSp().get()->getmetadataInfoVector();
  std::vector<QString> colnames =
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns();

  qDebug();
  mp_metadataModel =
    new QStandardItemModel(metadata_lines.size(), colnames.size(), this);

  setMetadataViewColNames();
  fillMetadataTableView();
  ui->metadata_View->setModel(mp_metadataModel);
  ui->metadata_View->setVisible(true);
  qDebug();
}

void
McqrParamAllQuantiDialog::fillMetadataTableView()
{
  std::vector<McqrMetadata *> metadata_lines =
    msp_project->getMcqrExperimentSp().get()->getmetadataInfoVector();
  std::vector<QString> colnames =
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns();
  QVariant data;

  qDebug() << metadata_lines.size();
  for(std::size_t row = 0; row < metadata_lines.size(); row++)
    {
      for(std::size_t col = 0; col < colnames.size(); col++)
        {
          if(col == 0)
            {
              data = metadata_lines.at(row)->m_msrunId;
            }
          else if(col == 1)
            {
              data = metadata_lines.at(row)->m_msrunFile;
            }
          else
            {
              data = metadata_lines.at(row)->m_otherData[colnames.at(col)];
            }
          QModelIndex index = mp_metadataModel->index(row, col, QModelIndex());
          mp_metadataModel->setData(index, data);
          data.clear();
        }
    }
  qDebug();
}

void
McqrParamAllQuantiDialog::setMetadataViewColNames()
{
  qDebug();
  QStringList list = QStringList(
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns().begin(),
    msp_project->getMcqrExperimentSp().get()->getmetadataColumns().end());
  qDebug();
  mp_metadataModel->setHorizontalHeaderLabels(list);
  qDebug();
}

void
McqrParamAllQuantiDialog::setMcqrExpSummary()
{
  McqrExpSummary summary;

  summary.m_fractioning = ui->fraction_switch->getSwitchValue();
  if(!summary.m_fractioning)
    {
      if(ui->fraction_name_line->text().isEmpty())
        {
          summary.m_fractionName = "All";
        }
      else
        {
          summary.m_fractionName = ui->fraction_name_line->text();
        }
    }
  summary.m_isotopicLabeling     = ui->label_switch->getSwitchValue();
  summary.m_quantificationMethod = ui->quanti_combobox->currentText();
  msp_project->getMcqrExperimentSp().get()->setMcqrExpSummary(summary);
}

void
McqrParamAllQuantiDialog::handleFractionNameEnabling()
{
  ui->fraction_name_label->setDisabled(ui->fraction_switch->getSwitchValue());
  ui->fraction_name_line->setDisabled(ui->fraction_switch->getSwitchValue());
}

MsRunAlignmentGroupSp
McqrParamAllQuantiDialog::checkMasschroqmlPath(QString masschroqml_name)
{
  qDebug() << masschroqml_name
           << " msp_project->getMsRunAlignmentGroupList().size()="
           << msp_project->getMsRunAlignmentGroupList().size();

  for(MsRunAlignmentGroupSp align_sp :
      msp_project->getMsRunAlignmentGroupList())
    {
      qDebug() << align_sp.get()->getMsRunAlignmentGroupName();
      QFileInfo masschroqml_path = QFileInfo(align_sp->getMassChroqmlPath());
      qDebug() << masschroqml_path.absoluteFilePath();
      if(masschroqml_path.exists() && masschroqml_path.isFile() &&
         masschroqml_path.baseName() == masschroqml_name)
        {
          // m_masschroqmlPath = align_sp->getMassChroqmlPath();
          return align_sp;
        }
    }
  MsRunAlignmentGroupSp all_msrun =
    msp_project.get()->getAllMsRunAlignmentGroup();

  QFileInfo masschroqml_path = QFileInfo(all_msrun->getMassChroqmlPath());
  qDebug() << masschroqml_path.absoluteFilePath();
  if(masschroqml_path.exists() && masschroqml_path.isFile() &&
     masschroqml_path.baseName() == masschroqml_name)
    {
      // m_masschroqmlPath = align_sp->getMassChroqmlPath();
      return all_msrun;
    }


  // file not found

  QString filename = QFileDialog::getOpenFileName(
    this,
    tr("Choose MassChroqML File"),
    "",
    tr("MassChroqML files (*.masschroqml);;all files (*)"));

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

      MsRunAlignmentGroupSp all_msrun =
        msp_project.get()->getAllMsRunAlignmentGroup();

      QFileInfo masschroqml_path = QFileInfo(filename);
      qDebug() << masschroqml_path.absoluteFilePath();
      if(masschroqml_path.exists() && masschroqml_path.isFile())
        {
          // m_masschroqmlPath = align_sp->getMassChroqmlPath();
          all_msrun.get()->setMassChroqmlPath(filename);
          return all_msrun;
        }
    }
  return nullptr;
}

bool
McqrParamAllQuantiDialog::getMcqrRunStatus()
{
  return m_runMCQR;
}

bool
McqrParamAllQuantiDialog::getMassChroqResultsUsed()
{
  return m_masschroqUsed;
}

McqrLoadDataMode
McqrParamAllQuantiDialog::getMcqrLoadDataMode()
{
  if(ui->fraction_switch->getSwitchValue() &&
     ui->label_switch->getSwitchValue())
    {
      return McqrLoadDataMode::both;
    }
  else if(!ui->fraction_switch->getSwitchValue() &&
          ui->label_switch->getSwitchValue())
    {
      return McqrLoadDataMode::label;
    }
  else if(ui->fraction_switch->getSwitchValue() &&
          !ui->label_switch->getSwitchValue())
    {
      return McqrLoadDataMode::fraction;
    }
  else
    {
      return McqrLoadDataMode::basic;
    }
}

const QFileInfo &
McqrParamAllQuantiDialog::getMetadataOdsFileInfo() const
{
    return m_metadataOdsFile;
}
