/**
 * \file pappsomspp/msrun/msrunreader.cpp
 * \date 29/05/2018
 * \author Olivier Langella
 * \brief base interface to read MSrun files
 */

/*******************************************************************************
 * Copyright (c) 2018 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of the PAPPSOms++ library.
 *
 *     PAPPSOms++ 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.
 *
 *     PAPPSOms++ 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 PAPPSOms++.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include <QDebug>

#include "msrunreader.h"
#include "../../pappsomspp/exception/exceptionnotfound.h"


int msRunReaderSPtrMetaTypeId =
  qRegisterMetaType<pappso::MsRunReaderSPtr>("pappso::MsRunReaderSPtr");


namespace pappso
{


bool
SpectrumCollectionHandlerInterface::shouldStop()
{
  return false;
}
void
SpectrumCollectionHandlerInterface::loadingEnded()
{
}
void
SpectrumCollectionHandlerInterface::spectrumListHasSize([
  [maybe_unused]] std::size_t size)
{
}
void
SpectrumCollectionHandlerInterface::setReadAhead(bool is_read_ahead)
{
  m_isReadAhead = is_read_ahead;
}

bool
SpectrumCollectionHandlerInterface::isReadAhead() const
{
  return m_isReadAhead;
}

bool
SpectrumCollectionHandlerInterface::needMsLevelPeakList(
  unsigned int ms_level) const
{
  if(needPeakList() == true)
    {
      if(ms_level < m_needPeakListByMsLevel.size())
        {
          return m_needPeakListByMsLevel[ms_level];
        }
      else
        return true;
    }
  else
    {
      return false;
    }
}
void
SpectrumCollectionHandlerInterface::setNeedMsLevelPeakList(
  unsigned int ms_level, bool want_peak_list)
{
  if(ms_level < m_needPeakListByMsLevel.size())
    {
      m_needPeakListByMsLevel[ms_level] = want_peak_list;
    }
}

bool
MsRunSimpleStatistics::needPeakList() const
{
  return false;
}


void
MsRunSimpleStatistics::loadingEnded()
{
  // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()"
  //<< "The data loading process ended.";
}


void
MsRunSimpleStatistics::setQualifiedMassSpectrum(
  const QualifiedMassSpectrum &qspectrum)
{
  unsigned int ms_level = qspectrum.getMsLevel();
  if(ms_level == 0)
    return;
  if(ms_level > m_countMsLevelSpectrum.size())
    {
      m_countMsLevelSpectrum.resize(ms_level);
    }
  m_countMsLevelSpectrum[ms_level - 1]++;
}


unsigned long
MsRunSimpleStatistics::getMsLevelCount(unsigned int ms_level) const
{
  if(ms_level == 0)
    return 0;
  if(ms_level > m_countMsLevelSpectrum.size())
    return 0;
  return (m_countMsLevelSpectrum[ms_level - 1]);
}


unsigned long
MsRunSimpleStatistics::getTotalCount() const
{
  unsigned long total = 0;
  for(unsigned long count : m_countMsLevelSpectrum)
    {
      total += count;
    }
  return total;
}


MsRunReaderScanNumberMultiMap::MsRunReaderScanNumberMultiMap()
{
  // qDebug();
}


MsRunReaderScanNumberMultiMap::~MsRunReaderScanNumberMultiMap()
{
  // qDebug();
}


bool
MsRunReaderScanNumberMultiMap::needPeakList() const
{
  return false;
}

void
MsRunReaderScanNumberMultiMap::setQualifiedMassSpectrum(
  const QualifiedMassSpectrum &qspectrum)
{
  qDebug() << " " << qspectrum.getMassSpectrumId().getNativeId();

  QStringList native_id_list =
    qspectrum.getMassSpectrumId().getNativeId().split("=");
  if(native_id_list.size() < 2)
    {
      return;
    }
  else
    {
      std::size_t scan_number = native_id_list.back().toULong();
      m_mmap_scan2index.insert(std::pair<std::size_t, std::size_t>(
        scan_number, qspectrum.getMassSpectrumId().getSpectrumIndex()));

      qDebug() << "scan number " << scan_number << "=>"
               << qspectrum.getMassSpectrumId().getSpectrumIndex();
    }
}

std::size_t
MsRunReaderScanNumberMultiMap::getSpectrumIndexFromScanNumber(
  std::size_t scan_number) const
{

  qDebug() << m_mmap_scan2index.size();

  auto it = m_mmap_scan2index.find(scan_number);

  if(it == m_mmap_scan2index.end())
    {
      throw ExceptionNotFound(
        QObject::tr("scan number %1 not found").arg(scan_number));
    }

  std::size_t index = it->second;

  it++;
  if((it != m_mmap_scan2index.end()) && (it->first == scan_number))
    {
      throw PappsoException(
        QObject::tr("scan number %1 found multiple times").arg(scan_number));
    }
  return index;
}


MsRunReader::MsRunReader(MsRunIdCstSPtr &ms_run_id) : mcsp_msRunId(ms_run_id)
{
}

MsRunReader::MsRunReader(const MsRunReader &other)
  : mcsp_msRunId(other.mcsp_msRunId)
{
  mpa_multiMapScanNumber = nullptr;
}


const MsRunIdCstSPtr &
MsRunReader::getMsRunId() const
{
  return mcsp_msRunId;
}


MsRunReader::~MsRunReader()
{
  if(mpa_multiMapScanNumber == nullptr)
    delete mpa_multiMapScanNumber;
}


std::size_t
MsRunReader::scanNumber2SpectrumIndex(std::size_t scan_number)
{
  qDebug() << " " << mpa_multiMapScanNumber;

  if(mpa_multiMapScanNumber == nullptr)
    {
      mpa_multiMapScanNumber = new MsRunReaderScanNumberMultiMap();
      readSpectrumCollection(*mpa_multiMapScanNumber);
    }
  try
    {
      return mpa_multiMapScanNumber->getSpectrumIndexFromScanNumber(
        scan_number);
    }

  catch(ExceptionNotFound &error)
    {
      throw ExceptionNotFound(QObject::tr("error reading file %1 : %2")
                                .arg(mcsp_msRunId.get()->getFileName())
                                .arg(error.qwhat()));
    }
  catch(PappsoException &error)
    {
      throw PappsoException(QObject::tr("error reading file %1 : %2")
                              .arg(mcsp_msRunId.get()->getFileName())
                              .arg(error.qwhat()));
    }
}


bool
MsRunReader::hasScanNumbers() const
{
  return false;
}

} // namespace pappso
