/**
 * \file /files/tandemparametersfile.cpp
 * \date 19/9/2017
 * \author Olivier Langella
 * \brief handles X!Tandem parameters file (presets)
 */

/*******************************************************************************
 * 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 "tandemparametersfile.h"
#include <QXmlStreamWriter>
#include <QDir>
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/exception/exceptionnotfound.h>


TandemParametersFile::TandemParametersFile(const QString &fasta_source)
  : _param_source(fasta_source)
{
  m_methodName = _param_source.baseName();
  qDebug() << fasta_source;
}
TandemParametersFile::TandemParametersFile(const QFileInfo &fasta_source)
  : _param_source(fasta_source)
{
  m_methodName = _param_source.baseName();
}
TandemParametersFile::TandemParametersFile(const TandemParametersFile &other)
  : _param_source(other._param_source)
{
  m_fileType              = other.m_fileType;
  m_isTandemParameterFile = other.m_isTandemParameterFile;
  m_methodName            = other.m_methodName;
}
TandemParametersFile::~TandemParametersFile()
{
}
const QString &
TandemParametersFile::getMethodName() const
{
  return m_methodName;
}

const QString
TandemParametersFile::getFilename() const
{
  return _param_source.fileName();
}

const QDir
TandemParametersFile::getAbsoluteDir() const
{
  return _param_source.absoluteDir();
}
const QString
TandemParametersFile::getAbsoluteFilePath() const
{
  return _param_source.absoluteFilePath();
}
bool
TandemParametersFile::exists() const
{
  return _param_source.exists();
}
void
TandemParametersFile::setDirectory(const QDir &directory)
{
  QFileInfo new_dir(QString("%1/%2")
                      .arg(directory.absolutePath())
                      .arg(_param_source.fileName()));
  _param_source = new_dir;
}

void
TandemParametersFile::setTandemParameters(const TandemParameters &parameters)
{

  QFile xml_file(_param_source.absoluteFilePath());
  QFile new_file(QString("%1/%2.xml")
                   .arg(_param_source.absolutePath())
                   .arg(parameters.getMethodName()));
  try
    {
      if(_param_source.absoluteFilePath() !=
         QFileInfo(new_file).absoluteFilePath())
        {
          if(xml_file.exists())
            {
              // move if renamed
              xml_file.remove();
            }
        }
      QXmlStreamWriter *p_out;
      if(new_file.open(QIODevice::WriteOnly))
        {

          _param_source.setFile(new_file);
          p_out = new QXmlStreamWriter();
          p_out->setDevice(&new_file);
          writeXmlParametersFile(p_out, parameters);
          new_file.close();
          delete p_out;
        }
      else
        {
          throw pappso::PappsoException(
            QObject::tr(
              "error : cannot open the XML X!Tandem parameter file : %1\n")
              .arg(new_file.fileName()));
        }
    }

  catch(pappso::PappsoException &error_pappso)
    {
      throw pappso::PappsoException(
        QObject::tr("error writing tandem preset file %1 : \n%2")
          .arg(QFileInfo(new_file).absoluteFilePath())
          .arg(error_pappso.qwhat()));
    }
  catch(std::exception &error)
    {
      throw pappso::PappsoException(
        QObject::tr("error writing tandem preset file %1 : \n%2")
          .arg(QFileInfo(new_file).absoluteFilePath())
          .arg(error.what()));
    }
}

TandemParameters
TandemParametersFile::getTandemParameters()
{

  qDebug();
  TandemParameters parameters;

  TandemParamParser tandem_param_parser;

  qDebug() << _param_source.absoluteFilePath();
  m_isTandemParameterFile = false;
  if(tandem_param_parser.readFile(_param_source.absoluteFilePath()))
    {

      qDebug();
      m_isTandemParameterFile = true;
      m_fileType              = ParamFileType::preset;
      parameters              = tandem_param_parser.getTandemParameters();
    }
  else
    {
      qDebug();
      throw pappso::PappsoException(
        QObject::tr("Error reading %1 X!Tandem preset file :\n %2")
          .arg(_param_source.absoluteFilePath())
          .arg(tandem_param_parser.errorString()));
    }


  qDebug();

  setTandemParametersFileType(tandem_param_parser);

  qDebug();

  if(m_fileType == ParamFileType::result)
    {
      m_methodName = tandem_param_parser.getMethodName();
    }
  parameters.setMethodName(getMethodName());

  qDebug();
  return parameters;
}

ParamFileType
TandemParametersFile::getTandemFileType() const
{
  qDebug();
  return m_fileType;
}

void
TandemParametersFile::writeXmlParametersFile(
  QXmlStreamWriter *p_out, const TandemParameters &parameters) const
{
  p_out->setAutoFormatting(true);
  p_out->writeStartDocument("1.0");

  //<?xml version="1.0" encoding="UTF-8"?>
  //<bioml label="example api document">
  //<note type="input" label="spectrum, parent monoisotopic mass error
  // units">ppm</note> <note type="input" label="spectrum, parent monoisotopic
  // mass error minus">10</note>
  p_out->writeStartElement("bioml");
  p_out->writeAttribute("label", "example api document");
  for(const QString &label : parameters.getMapLabelValue().keys())
    {
      //<note type="input" label="list path, default
      // parameters">/gorgone/pappso/tmp/xtpcpp.xBIhCg/QExactive_analysis_FDR_nosemi_mutation.xml</note>
      //<note type="input" label="list path, taxonomy
      // information">/gorgone/pappso/tmp/xtpcpp.xBIhCg/database.xml</note>
      if(label.startsWith("output, ") || label.startsWith("protein, ") ||
         (label == "refine") || label.startsWith("refine, ") ||
         label.startsWith("residue, ") || label.startsWith("scoring, ") ||
         label.startsWith("spectrum, "))
        {
          p_out->writeStartElement("note");
          p_out->writeAttribute("type", "input");
          p_out->writeAttribute("label", label);
          p_out->writeCharacters(parameters.getMapLabelValue().value(label));
          p_out->writeEndElement();
        }
    }
  //</bioml>
  p_out->writeEndElement();
  p_out->writeEndDocument();
}

void
TandemParametersFile::setTandemParametersFileType(
  const TandemParamParser &param_parser)
{
  if(this->exists())
    {
      try
        {
          qDebug() << (int)m_fileType;
          m_fileType = param_parser.getParamFileType();
          qDebug() << (int)m_fileType;
        }
      catch(pappso::ExceptionNotFound &error)
        {
          throw pappso::ExceptionNotFound(
            QObject::tr("error : %1 Doesn't exist'\noriginal error:\n%2")
              .arg(_param_source.fileName())
              .arg(error.qwhat()));
          m_fileType = ParamFileType::no_file;
        }
      catch(pappso::PappsoException &error)
        {
          throw pappso::PappsoException(
            QObject::tr("error : %1 Doesn't exist'\noriginal error:\n%2")
              .arg(_param_source.fileName())
              .arg(error.qwhat()));
          m_fileType = ParamFileType::not_xtandem;
        }
    }
}
