/**
 * \file output/ods/odsexport.cpp
 * \date 11/4/2017
 * \author Olivier Langella
 * \brief ODS export
 */

/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.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/>.
 *
 * Contributors:
 *     Olivier Langella <olivier.langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include "odsexport.h"
#include "simplesheet.h"
#include "proteinsheet.h"
#include "peptidesheet.h"
//#include "spectrasheet.h"
#include "spectrasheetall.h"
#include "validpsmsheet.h"
#include "peptidepossheet.h"
#include "qvaluessheet.h"
#include "comparspectrasheet.h"
#include "comparspecificspectrasheet.h"
#include "comparspectrabypeptide.h"
#include "infosheet.h"
#include "samplesheet.h"
#include "groupingsheet.h"
#include "ptm/ptmislandsheet.h"
#include "ptm/ptmspectrasheet.h"
#include "ptm/ptmgroupingsheet.h"
#include "ptm/comparptmislandsheet.h"
#include "mass_delta/validmassdeltasheet.h"
#include "mass_delta/notvalidmassdeltasheet.h"
#include <QSettings>
#include <odsstream/odsexception.h>
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/exception/exceptioninterrupted.h>

OdsExport::OdsExport(ProjectSp project) : _p_project(project)
{
}
void
OdsExport::setEvenOrOddStyle(unsigned int number, CalcWriterInterface *p_writer)
{

  if(number % 2)
    { /* x is odd */
      p_writer->setTableCellStyleRef(_odd_style);
    }
  else
    {
      p_writer->setTableCellStyleRef(_even_style);
    }
}

void
OdsExport::write(CalcWriterInterface *p_writer,
                 ExportSpreadsheetDialog *export_spreadsheet_dialog,
                 WorkMonitorInterface *p_monitor)
{
  QSettings settings;

  try
    {
      OdsTableCellStyle style;
      style.setBackgroundColor(QColor("red"));
      _odd_style = p_writer->getTableCellStyleRef(style);
      style.setBackgroundColor(QColor("orange"));
      _even_style = p_writer->getTableCellStyleRef(style);

      InfoSheet(p_writer, _p_project.get());

      if(export_spreadsheet_dialog->isProjectParameters())
        {
          p_monitor->message(QObject::tr("writing parameters"));
          _p_project.get()->getProjectParameters().writeParameters(*p_writer);
        }
      if(export_spreadsheet_dialog->isGroupingSheet())
        {
          p_monitor->message(QObject::tr("writing groups"));
          GroupingSheet(this, p_writer, _p_project.get());
        }
      if(export_spreadsheet_dialog->isSimpleSheet())
        {
          SimpleSheet(p_writer, _p_project.get(), p_monitor->getSubMonitor());
        }
      if(export_spreadsheet_dialog->isProteinSheet())
        {
          p_monitor->message(QObject::tr("writing proteins"));
          ProteinSheet(this, p_writer, _p_project.get());
        }
      if(export_spreadsheet_dialog->isPeptideSheet())
        {
          p_monitor->message(QObject::tr("writing peptides"));
          PeptideSheet(this, p_writer, _p_project.get());
        }
      bool mobility_informations =
        settings.value("export_ods/spectra_mobility_informations", "false")
          .toBool();
      if(export_spreadsheet_dialog->isSpectraSheet())
        {
          p_monitor->message(QObject::tr("writing spectra"));
          qDebug() << " mobility_informations=" << mobility_informations;
          SpectraSheet(this, p_writer, _p_project.get(), mobility_informations);
        }
      if(export_spreadsheet_dialog->isSpectraSheetAll())
        {
          p_monitor->message(QObject::tr("writing PSMs"));
          SpectraSheetAll(this, p_writer, _p_project.get());
        }

      if(export_spreadsheet_dialog->isValidPsmSheet())
        {
          p_monitor->message(QObject::tr("writing all valid PSMs"));
          ValidPsmSheet(this, p_writer, _p_project.get());
        }
      if(export_spreadsheet_dialog->isPeptidePosSheet())
        {
          p_monitor->message(
            QObject::tr("writing peptide and positions on proteins"));
          PeptidePosSheet(this, p_writer, _p_project.get());
        }

      if(export_spreadsheet_dialog->isMassDeltaSheet())
        {
          p_monitor->message(QObject::tr("writing mass delta for valid PSMs"));
          ValidMassDeltaSheet(this, p_writer, _p_project.get());
          p_monitor->message(
            QObject::tr("writing mass delta for not valid PSMs"));
          NotValidMassDeltaSheet(this, p_writer, _p_project.get());
        }
      if(_p_project->getProjectMode() != ProjectMode::individual)
        {
          // export compar sheets not possible in individual mode

          if(settings.value("export_ods/peptidomiccomparspectra", "false")
               .toBool())
            {
              p_monitor->message(
                QObject::tr("writing spectra comparisons for peptidomic"));
              ComparSpectraByPeptide(this, p_writer, _p_project.get())
                .writeSheet();
            }
          if(settings.value("export_ods/comparspectra", "true").toBool())
            {
              p_monitor->message(QObject::tr("writing spectra comparisons"));
              ComparSpectraSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparspecificspectra", "true")
               .toBool())
            {
              p_monitor->message(
                QObject::tr("writing specific spectra comparisons"));
              ComparSpecificSpectraSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparuniquesequence", "true").toBool())
            {
              p_monitor->message(
                QObject::tr("writing unique sequence comparisons"));
              ComparSequenceSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparspecificuniquesequence", "true")
               .toBool())
            {
              p_monitor->message(
                QObject::tr("writing specific unique sequence comparisons"));
              ComparSpecificSequenceSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparpai", "true").toBool())
            {
              p_monitor->message(QObject::tr("writing PAI comparisons"));
              ComparPaiSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparempai", "true").toBool())
            {
              p_monitor->message(QObject::tr("writing emPAI comparisons"));
              ComparEmpaiSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
          if(settings.value("export_ods/comparnsaf", "true").toBool())
            {
              p_monitor->message(QObject::tr("writing NSAF comparisons"));
              ComparNsafSheet(
                this, p_writer, _p_project.get(), p_monitor->getSubMonitor())
                .writeSheet();
            }
        }
      if(export_spreadsheet_dialog->isSampleSheet())
        {
          p_monitor->message(QObject::tr("writing samples"));
          SampleSheet(this, p_writer, _p_project.get());
        }

      if(export_spreadsheet_dialog->isQvaluesSheet())
        {
          p_monitor->message(QObject::tr("writing q-values"));
          QvaluesSheet(this, p_writer, _p_project);
        }
      if(_p_project->hasPtmExperiment())
        {
          p_monitor->message(QObject::tr("writing PTM grouping"));
          PtmGroupingSheet(this, p_writer, _p_project.get());


          if(export_spreadsheet_dialog->isPtmIslandSheet())
            {
              p_monitor->message(QObject::tr("writing PTM islands"));
              PtmIslandSheet(this, p_writer, _p_project.get());
              p_monitor->message(QObject::tr("writing compar PTM islands"));
              ComparPtmIslandSheet(this, p_writer, _p_project.get());
            }

          if(export_spreadsheet_dialog->isPtmSpectraSheet())
            {
              p_monitor->message(QObject::tr("writing PTM spectra"));
              PtmSpectraSheet(this, p_writer, _p_project.get());
            }
        }
    }
  catch(pappso::ExceptionInterrupted &error)
    {
      throw pappso::PappsoException(
        QObject::tr("ODS file not completed, interrupted by the user:\n %1")
          .arg(error.qwhat()));
    }
  catch(OdsException &error)
    {
      throw pappso::PappsoException(
        QObject::tr("Error writing ODS file :\n%1").arg(error.qwhat()));
    }
}
