/**
 * \file pappsomspp/processing/cbor/cborstreamwriter.cpp
 * \date 05/07/2025
 * \author Olivier Langella
 * \brief PAPPSO CBOR stream writer
 */

/*******************************************************************************
 * Copyright (c) 2025 Olivier Langella <Olivier.Langella@universite-paris-saclay.fr>.
 *
 * This file is part of PAPPSOms-tools.
 *
 *     PAPPSOms-tools 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-tools 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-tools.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "cborstreamwriter.h"
#include <QDateTime>
#include <QThreadPool>
#include "pappsomspp/core/utils.h"
#include <QCborValue>

namespace pappso
{
namespace cbor
{
CborStreamWriter::CborStreamWriter(QByteArray *data) : QCborStreamWriter(data)
{
}

CborStreamWriter::CborStreamWriter(QIODevice *device) : QCborStreamWriter(device)
{
}


CborStreamWriter::~CborStreamWriter()
{
}


const QString &
CborStreamWriter::getUuid() const
{
  return m_uuid;
}

void
CborStreamWriter::writeInformations(const QString &software_name,
                                    const QString &software_version,
                                    const QString &type,
                                    const QString &operation)
{
  append("informations");
  startMap();
  append(QLatin1String("software"));
  append(software_name);
  append(QLatin1String("version"));
  append(software_version);
  append(QLatin1String("type"));
  append(type);
  append(QLatin1String("operation"));
  append(operation);
  append(QLatin1String("cpu_used"));
  append(QThreadPool::globalInstance()->maxThreadCount());
  append(QLatin1String("pappsomspp_version"));
  append(pappso::Utils::getVersion());
  append(QLatin1String("sysinfo_machine_hostname"));
  append(QSysInfo::machineHostName());
  append(QLatin1String("sysinfo_product_name"));
  append(QSysInfo::prettyProductName());
  append(QLatin1String("timestamp"));
  append(QDateTime::currentDateTime().toString(Qt::ISODate));

  append(QLatin1String("uuid"));
  m_uuid = QUuid::createUuid().toString();
  append(m_uuid);
  endMap();
}


void
CborStreamWriter::writeArray(const std::vector<std::size_t> &int_list)
{
  startArray(int_list.size());
  for(auto num : int_list)
    {
      append((quint64)num);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const std::vector<double> &double_list)
{
  startArray(double_list.size());
  for(auto num : double_list)
    {
      append(num);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const std::vector<int> &positions)
{

  startArray(positions.size());
  for(auto num : positions)
    {
      append(num);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const std::vector<std::uint8_t> &small_uint_list)
{

  startArray(small_uint_list.size());
  for(int num : small_uint_list)
    {
      append(num);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const std::vector<qint64> &int_list)
{

  startArray(int_list.size());
  for(auto num : int_list)
    {
      append(num);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const QStringList &str_list)
{
  startArray(str_list.size());
  for(auto str_item : str_list)
    {
      append(str_item);
    }
  endArray();
}

void
CborStreamWriter::writeArray(const std::vector<QString> &str_list)
{
  startArray(str_list.size());
  for(auto str_item : str_list)
    {
      append(str_item);
    }
  endArray();
}

void
CborStreamWriter::writeCborMap(const QCborMap &cbor_map)
{
  QCborValue(cbor_map).toCbor(*this);
}

void
CborStreamWriter::writeCborArray(const QCborArray &cbor_array)
{
  QCborValue(cbor_array).toCbor(*this);
}

void
CborStreamWriter::writeTrace(const pappso::Trace &trace,
                             const QString &x_label,
                             const QString &y_label)
{
  startMap(2);
  append(x_label);
  writeArray(trace.xValues());
  append(y_label);
  writeArray(trace.yValues());
  endMap();
}


void
CborStreamWriter::writeXicCoord(const pappso::XicCoord &xic_coord)
{
  startMap();
  xic_coord.writeCborStream(*this);

  if(xic_coord.xicSptr.get() != nullptr)
    {
      append("xic");
      writeTrace(*xic_coord.xicSptr.get(), "rt", "intensities");
    }
  endMap();
}


void
CborStreamWriter::writeXicCoordList(const std::vector<pappso::XicCoordSPtr> &xic_coord_list)
{

  startArray(xic_coord_list.size());
  for(auto &xic_coord_sp : xic_coord_list)
    {
      writeXicCoord(*xic_coord_sp.get());
    }
  endArray();
}

} // namespace cbor
} // namespace pappso
