/**
 * \file pappsomspp/processing/cbor/mzcbor/converttomzml.cpp
 * \date 30/11/2025
 * \author Olivier Langella
 * \brief convert mzcbor to mzML
 */

/*******************************************************************************
 * 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 "converttomzml.h"
#include "cvparam.h"
#include "binarydataarray.h"
#include "pappsomspp/core/processing/cbor/mzcbor/cvparammap.h"

namespace pappso
{
namespace cbor
{
namespace mzcbor
{
ConvertToMzml::ConvertToMzml(QXmlStreamWriter *p_writer) : mp_writer(p_writer)
{
}

ConvertToMzml::~ConvertToMzml()
{
}

void
ConvertToMzml::close()
{
}

void
pappso::cbor::mzcbor::ConvertToMzml::readCbor(QFile *cborp, pappso::UiMonitorInterface &monitor)
{
  qDebug();
  initCborReader(cborp);

  qDebug();
  if(mpa_cborReader->isMap())
    {
      readRoot(monitor);
    }
  qDebug();
}

void
pappso::cbor::mzcbor::ConvertToMzml::readCbor(QIODevice *cborp, pappso::UiMonitorInterface &monitor)
{
  qDebug();
  initCborReader(cborp);

  qDebug();
  if(mpa_cborReader->isMap())
    {
      readRoot(monitor);
    }
  qDebug();
}


void
pappso::cbor::mzcbor::ConvertToMzml::readRoot(pappso::UiMonitorInterface &monitor [[maybe_unused]])
{
  qDebug();
  mpa_cborReader->enterContainer();

  while(getExpectedString())
    {

      if(m_expectedString == "mzCBOR")
        {
          m_isMzcbor = true;
          mpa_cborReader->next();
        }
      else if(m_expectedString == "mzML")
        {

          QCborMap mzml_cbor;
          mpa_cborReader->readCborMap(mzml_cbor);
          //<mzML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          // xsi:schemaLocation="http://psi.hupo.org/ms/mzml
          // http://psidev.info/files/ms/mzML/xsd/mzML1.1.0.xsd" version="1.1.0"
          // id="20120906_balliau_extract_1_A01_urnb-1" xmlns="http://psi.hupo.org/ms/mzml">


          mp_writer->setAutoFormatting(true);
          mp_writer->writeStartDocument("1.0");
          mp_writer->writeDefaultNamespace(mzml_cbor.value("xmlns").toString());

          mp_writer->writeNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");

          mp_writer->writeStartElement("mzML");

          mp_writer->writeAttribute("http://www.w3.org/2001/XMLSchema-instance",
                                    "schemaLocation",
                                    mzml_cbor.value("schemaLocation").toString());


          for(auto &str_key : mzml_cbor.keys())
            {
              if((str_key != "xmlns") && (str_key != "schemaLocation"))
                {
                  mp_writer->writeAttribute(str_key.toString(),
                                            mzml_cbor.value(str_key).toString());
                }
            }

          m_isMzcbor = true;
          // getExpectedString();
          // qDebug() << m_expectedString;
          // mpa_cborReader->next();

          while(getExpectedString())
            {
              qDebug() << m_expectedString;
              writeElementInMzml(m_expectedString, monitor);
            }
          mp_writer->writeEndElement();
        }
    }
  mpa_cborReader->leaveContainer();
  mp_writer->writeEndDocument();
}


void
pappso::cbor::mzcbor::ConvertToMzml::writeElementInMzml(const QString &name,
                                                        pappso::UiMonitorInterface &monitor
                                                        [[maybe_unused]])
{
  bool is_array = false;
  if(name == "cvParam")
    { // this is an array
      qDebug();
      CvParamMap cvparam_map;
      cvparam_map.fromCbor(*mpa_cborReader);
      for(auto &cvparam_pair : cvparam_map)
        {
          cvparam_pair.second.toMzml(*mp_writer);
        }
    }
  else if(name == "binaryDataArray")
    {

      mp_writer->writeStartElement("binaryDataArrayList");

      mp_writer->writeAttribute("count", QString("%1").arg(mpa_cborReader->length()));
      mpa_cborReader->enterContainer();
      while(mpa_cborReader->hasNext())
        {
          BinaryDataArray binary_data_array;
          binary_data_array.fromCbor(*mpa_cborReader);
          binary_data_array.toMzml(*mp_writer);
        }

      mpa_cborReader->leaveContainer();

      mp_writer->writeEndElement();
    }
  else
    {
      if(mpa_cborReader->isArray())
        {
          is_array = true;
        }
      else if(mpa_cborReader->isMap())
        {
        }
      else
        {
          // error
          qWarning() << "not a map, not an array";
        }
      if(is_array)
        {
          mpa_cborReader->enterContainer();
          while(mpa_cborReader->hasNext())
            {
              writeElementInMzml(name, monitor);
            }

          mpa_cborReader->leaveContainer();
        }
      else
        {
          mp_writer->writeStartElement(name);
          mpa_cborReader->enterContainer();

          while(getExpectedString())
            {
              qDebug() << m_expectedString;
              QString current_attribute = m_expectedString;
              if(mpa_cborReader->isContainer())
                {
                  qDebug() << current_attribute;
                  writeElementInMzml(current_attribute, monitor);
                }
              else if(mpa_cborReader->isInteger())
                {
                  qDebug() << current_attribute;
                  mp_writer->writeAttribute(current_attribute,
                                            QString("%1").arg(mpa_cborReader->toInteger()));
                  mpa_cborReader->next();
                }
              else if(mpa_cborReader->isUnsignedInteger())
                {
                  qDebug() << current_attribute;
                  mp_writer->writeAttribute(current_attribute,
                                            QString("%1").arg(mpa_cborReader->toUnsignedInteger()));
                }
              else if(mpa_cborReader->isString())
                {
                  getExpectedString();
                  qDebug() << current_attribute;
                  mp_writer->writeAttribute(current_attribute, m_expectedString);
                }
              else
                {
                  qDebug() << current_attribute;
                  mpa_cborReader->next();
                }
            }

          mpa_cborReader->leaveContainer();

          mp_writer->writeEndElement();
        }
    }
}

} // namespace mzcbor
} // namespace cbor
} // namespace pappso
