/**
 * \file src/input/mzidentml/msrunlocationreader.cpp
 * \date 16/7/2022
 * \author Olivier Langella
 * \brief parse mzIdentML result file to only get the msrun
 */


/*******************************************************************************
 * Copyright (c) 2022 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 "msrunlocationreader.h"
#include <QDebug>
#include <QFileInfo>

MsRunLocationReader::MsRunLocationReader()
{
}

MsRunLocationReader::~MsRunLocationReader()
{
}


void
MsRunLocationReader::readStream()
{

  bool is_spectradata = false;

  qDebug();
  if(m_qxmlStreamReader.readNextStartElement())
    {
      qDebug() << m_qxmlStreamReader.name();
      if(m_qxmlStreamReader.name().toString() == "MzIdentML")
        {
          while(m_qxmlStreamReader.readNextStartElement())
            {
              qDebug() << m_qxmlStreamReader.name();
              if(m_qxmlStreamReader.name().toString() ==
                 "AnalysisProtocolCollection")
                {
                  //<AnalysisProtocolCollection>
                  readAdditionalSearchParams();
                }
              else if(m_qxmlStreamReader.name().toString() ==
                      "AnalysisSoftwareList")
                {
                  readAnalysisSoftwareList();
                }
              else if(m_qxmlStreamReader.name().toString() == "DataCollection")
                {
                  //<DataCollection
                  while(m_qxmlStreamReader.readNextStartElement())
                    {
                      qDebug() << m_qxmlStreamReader.name();
                      if(m_qxmlStreamReader.name().toString() != "Inputs")
                        {
                          m_qxmlStreamReader.skipCurrentElement();
                        }
                      else
                        {
                          // <Inputs>
                          while(m_qxmlStreamReader.readNextStartElement())
                            {
                              qDebug() << m_qxmlStreamReader.name();
                              if(m_qxmlStreamReader.name().toString() ==
                                 "SpectraData")
                                {
                                  is_spectradata = true;
                                  readSpectraData();
                                }
                              else
                                {
                                  m_qxmlStreamReader.skipCurrentElement();
                                }
                            }
                          if(is_spectradata == false)
                            {
                              m_qxmlStreamReader.raiseError(
                                QObject::tr("no SpectraData"));
                            }
                        }
                    }

                  if(is_spectradata == false)
                    {
                      m_qxmlStreamReader.raiseError(
                        QObject::tr("no SpectraData"));
                    }
                }
              else
                {
                  m_qxmlStreamReader.skipCurrentElement();
                }
            }
        }
      else
        {
          m_qxmlStreamReader.raiseError(QObject::tr("Not an MzIdentML file"));
          m_qxmlStreamReader.skipCurrentElement();
        }
    }

  else
    {
      m_qxmlStreamReader.raiseError(QObject::tr("Not an MzIdentML file"));
      m_qxmlStreamReader.skipCurrentElement();
    }
}

const std::vector<MsRunLocationReader::SpectraData> &
MsRunLocationReader::getSpectraDataList() const
{
  return m_spectraDataList;
}


//<SpectraData
// location="/home/thierry/test/MS-GF+/20170308_test_dig_Liquide_01.mzXML"
// id="SID_1" name="20170308_test_dig_Liquide_01.mzXML">
//      <FileFormat>
//        <cvParam cvRef="PSI-MS" accession="MS:1000566" name="ISB mzXML
//        file"/>
//      </FileFormat>
//      <SpectrumIDFormat>
//        <cvParam cvRef="PSI-MS" accession="MS:1000776" name="scan number
//        only nativeID format"/>
//      </SpectrumIDFormat>
//    </SpectraData>

void
MsRunLocationReader::readSpectraData()
{
  qDebug();
  MsRunLocationReader::SpectraData spectra_data;

  spectra_data.id = m_qxmlStreamReader.attributes().value("id").toString();
  spectra_data.location =
    m_qxmlStreamReader.attributes().value("location").toString();
  spectra_data.name = m_qxmlStreamReader.attributes().value("name").toString();

  if(spectra_data.id.isEmpty())
    {
      m_qxmlStreamReader.raiseError(
        QObject::tr("ERROR : SpectraData id is empty"));
    }
  if(spectra_data.location.isEmpty())
    {
      m_qxmlStreamReader.raiseError(
        QObject::tr("ERROR : SpectraData location is empty"));
    }

  if(spectra_data.name.isEmpty())
    {
      spectra_data.name = QFileInfo(spectra_data.location).baseName();
    }
  m_spectraDataList.push_back(spectra_data);
  /*
      <SpectraData
     location="/home/langella/data/bruker/200ngHeLaPASEF_2min_compressed.d/analysis.tdf"
     name="analysis.tdf" id="SID_1"> <FileFormat> <cvParam
     accession="MS:1000058" cvRef="PSI-MS" name="mzML file"/>
          </FileFormat>
          <SpectrumIDFormat>
              <cvParam accession="MS:1000768" cvRef="PSI-MS" name="Thermo
     nativeID format"/>
          </SpectrumIDFormat>
      </SpectraData>
      */
  while(m_qxmlStreamReader.readNextStartElement())
    {

      if((m_qxmlStreamReader.name().toString() == "FileFormat") ||
         (m_qxmlStreamReader.name().toString() == "SpectrumIDFormat"))
        {

          QString cvparam_name = m_qxmlStreamReader.name().toString();
          while(m_qxmlStreamReader.readNextStartElement())
            {
              if(m_qxmlStreamReader.name().toString() == "cvParam")
                {
                  //<cvParam     accession="MS:1000058" cvRef="PSI-MS"
                  // name="mzML file"/>
                  //<cvParam accession="MS:1002817" cvRef="PSI-MS" name="Bruker
                  // TDF format"/>
                  m_projectParameters.setProjectParam(readCvParam(
                    pappso::ProjectParamCategory::instrument,
                    QString("cvparam_SpectraData%1").arg(cvparam_name)));
                  m_qxmlStreamReader.skipCurrentElement();
                }
              else
                {
                  m_qxmlStreamReader.skipCurrentElement();
                }
            }
        }
      else
        {
          m_qxmlStreamReader.skipCurrentElement();
        }
    }
  qDebug();
}


void
MsRunLocationReader::readAdditionalSearchParams()
{
  qDebug();
  //<SpectrumIdentificationProtocol
  while(m_qxmlStreamReader.readNextStartElement())
    {
      qDebug() << m_qxmlStreamReader.name();
      if(m_qxmlStreamReader.name().toString() !=
         "SpectrumIdentificationProtocol")
        {
          m_qxmlStreamReader.skipCurrentElement();
        }
      else
        {
          //<SpectrumIdentificationProtocol analysisSoftware_ref =
          //"ID_software"
          // id =     "SearchProtocol_1">
          while(m_qxmlStreamReader.readNextStartElement())
            {
              qDebug() << m_qxmlStreamReader.name();
              if(m_qxmlStreamReader.name().toString() !=
                 "AdditionalSearchParams")
                {
                  m_qxmlStreamReader.skipCurrentElement();
                }
              else
                {

                  while(m_qxmlStreamReader.readNextStartElement())
                    {
                      qDebug() << m_qxmlStreamReader.name();
                      if(m_qxmlStreamReader.name().toString() != "userParam")
                        {
                          m_qxmlStreamReader.skipCurrentElement();
                        }
                      else
                        {
                          //< userParam name = "xtandem_pr
                          m_projectParameters.setProjectParam(readUserParam());

                          m_qxmlStreamReader.skipCurrentElement();
                        }
                    }
                }
            }
        }
    }
}

pappso::ProjectParam
MsRunLocationReader::readCvParam(pappso::ProjectParamCategory category,
                                 const QString &name) const
{

  QString accession =
    m_qxmlStreamReader.attributes().value("accession").toString();
  //<cvParam accession="MS:1000058" cvRef="PSI-MS" name="mzML file"/>
  //<cvParam accession="MS:1000768" cvRef="PSI-MS" name="Thermo nativeID
  // format"/>
  pappso::ProjectParam project_param({category, name, QVariant(accession)});
  return project_param;
}


pappso::ProjectParam
MsRunLocationReader::readUserParam() const
{
  pappso::ProjectParam project_param(
    {pappso::ProjectParamCategory::identification,
     m_qxmlStreamReader.attributes().value("name").toString(),
     QVariant()});
  QString value = m_qxmlStreamReader.attributes().value("value").toString();
  bool ok;
  int int_value(value.toInt(&ok));
  if(ok)
    {
      project_param.value.setValue(int_value);
    }
  else
    {
      double d_value(value.toDouble(&ok));
      if(ok)
        {
          project_param.value.setValue(d_value);
        }
      else
        {
          project_param.value.setValue(value);
        }
    }
  return project_param;
}

const pappso::ProjectParameters &
MsRunLocationReader::getProjectParameters() const
{
  return m_projectParameters;
}


void
MsRunLocationReader::readAnalysisSoftwareList()
{


  pappso::ProjectParam project_param(
    {pappso::ProjectParamCategory::identification, "", QVariant()});

  while(m_qxmlStreamReader.readNextStartElement())
    {
      if(m_qxmlStreamReader.name().toString() == "AnalysisSoftware")
        {

          // <AnalysisSoftware version="0.0.9" name="DeepProt" id="as1">

          project_param.name = "AnalysisSoftware_name";
          project_param.value.setValue(
            m_qxmlStreamReader.attributes().value("name").toString());
          m_projectParameters.setProjectParam(project_param);
          project_param.name = "AnalysisSoftware_version";
          project_param.value.setValue(
            m_qxmlStreamReader.attributes().value("version").toString());
          m_projectParameters.setProjectParam(project_param);
          m_qxmlStreamReader.skipCurrentElement();
        }
      else
        {
          m_qxmlStreamReader.skipCurrentElement();
        }
    }
}
