/**
 * \file pappsomspp/xicextractor/private/msrunslice.cpp
 * \date 12/05/2018
 * \author Olivier Langella
 * \brief one mz slice (1 dalton) of an MsRun
 */

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

#include "msrunslice.h"
#include "../../trace/datapoint.h"
#include "pappsomspp/core/pappsoexception.h"
#include "pappsomspp/core/exception/exceptionoutofrange.h"
#include <QDebug>

namespace pappso
{

MsRunSlice::MsRunSlice()
{
  m_sliceNumber = 0;
}

MsRunSlice::MsRunSlice(const MsRunSlice &other)
{
  m_sliceNumber  = other.m_sliceNumber;
  m_spectrumList = other.m_spectrumList;
}
MsRunSlice::~MsRunSlice()
{
}

MsRunSliceSPtr
MsRunSlice::makeMsRunSliceSp() const
{
  return std::make_shared<const MsRunSlice>(*this);
}

void
MsRunSlice::setSliceNumber(unsigned int slice_number)
{
  m_sliceNumber = slice_number;
}

unsigned int
MsRunSlice::getSliceNumber() const
{
  return m_sliceNumber;
}

std::size_t
MsRunSlice::size() const
{
  return m_spectrumList.size();
}

void
MsRunSlice::setSize(std::size_t size)
{
  m_spectrumList.resize(size);
}
void
MsRunSlice::clear()
{
  m_spectrumList.clear();
  m_sliceNumber = 0;
}

void
MsRunSlice::setSpectrum(std::size_t i, const MassSpectrum &spectrum)
{
  try
    {
      m_spectrumList[i] = spectrum;
    }
  catch(std::exception &error)
    {
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
      throw pappso::ExceptionOutOfRange(QObject::tr("unable to access spectrum %1 (size=%2) %3")
                                          .arg(i)
                                          .arg(m_spectrumList.size())
                                          .arg(error.what()));
    }
}

MassSpectrum &
MsRunSlice::getSpectrum(std::size_t i)
{
  try
    {
      return m_spectrumList.at(i);
    }
  catch(std::exception &error)
    {
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
      throw pappso::ExceptionOutOfRange(QObject::tr("unable to get spectrum %1 (size=%2) %3")
                                          .arg(i)
                                          .arg(m_spectrumList.size())
                                          .arg(error.what()));
    }
}
const MassSpectrum &
MsRunSlice::getSpectrum(std::size_t i) const
{
  try
    {
      return m_spectrumList.at(i);
    }
  catch(std::exception &error)
    {
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
      throw pappso::ExceptionOutOfRange(QObject::tr("unable to get spectrum %1 (size=%2) %3")
                                          .arg(i)
                                          .arg(m_spectrumList.size())
                                          .arg(error.what()));
    }
}

void
MsRunSlice::appendToStream(QDataStream &outstream, std::size_t ipos) const
{

  for(auto &&spectrum : m_spectrumList)
    {
      outstream << (quint32)ipos;
      outstream << spectrum;
      ipos++;
    }
}

QDataStream &
operator>>(QDataStream &instream, MsRunSlice &slice)
{

  quint32 vector_size       = 0;
  quint32 slice_number      = 0;
  quint32 spectrum_position = 0;
  DataPoint peak;

  if(!instream.atEnd())
    {
      instream >> slice_number;
      instream >> vector_size;
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__
               << " vector_size=" << vector_size;
      slice.setSize(vector_size);

      slice.setSliceNumber(slice_number);
      while(!instream.atEnd())
        {
          instream >> spectrum_position;
          MassSpectrum spectrum;
          try
            {
              instream >> spectrum;
            }
          catch(PappsoException &error)
            {
              throw PappsoException(QString("error in QDataStream unserialize operator>> of "
                                            "MsRunSlice %2 on %3:\n%1")
                                      .arg(error.qwhat())
                                      .arg(spectrum_position)
                                      .arg(vector_size));
            }
          slice.setSpectrum(spectrum_position, spectrum);

          if(instream.status() != QDataStream::Ok)
            {
              throw PappsoException(QString("error in QDataStream unserialize operator>> of "
                                            "MsRunSlice :\nread datastream failed status=%1")
                                      .arg(instream.status()));
            }
        }
    }

  if(slice.size() != vector_size)
    {
      throw PappsoException(QString("error in QDataStream unserialize operator>> of MsRunSlice "
                                    "slice.size() != vector_size :\n %1 %2:")
                              .arg(slice.size())
                              .arg(vector_size));
    }

  return instream;
}


} // namespace pappso
