/**
 * \file src/saxreader/qxmlstreamreadercontentxml.h
 * \date 28/4/2022
 * \author Olivier Langella
 * \brief ODS content XML parser
 */

/*******************************************************************************
 * Copyright (c) 2022 Olivier Langella <Olivier.Langella@u-psud.fr>.
 *
 * This file is part of libodsstream.
 *
 *     libodsstream 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.
 *
 *     libodsstream 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 libodsstream.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#include "qxmlstreamreadercontentxml.h"
#include <QDebug>

QXmlStreamReaderContentXml::QXmlStreamReaderContentXml(OdsDocReader &ods_reader)
  : m_odsReader(ods_reader)
{
}

QXmlStreamReaderContentXml::~QXmlStreamReaderContentXml()
{
}

bool
QXmlStreamReaderContentXml::read()
{

  if(readNextStartElement())
    {
      qDebug() << qualifiedName();
      /*
       * <office:document-content
       * xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
       * xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
       * xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
       * xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
       * xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0"
       * xmlns:dc="http://purl.org/dc/elements/1.1/"
       * xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
       * xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
       * xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
       * xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
       * xmlns:grddl="http://www.w3.org/2003/g/data-view#"
       * xmlns:math="http://www.w3.org/1998/Math/MathML"
       * xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
       * xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
       * xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"
       * xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
       * xmlns:ooo="http://openoffice.org/2004/office"
       * xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
       * xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
       * xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
       * xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
       * xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
       * xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
       * xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
       * xmlns:xforms="http://www.w3.org/2002/xforms"
       * xmlns:xhtml="http://www.w3.org/1999/xhtml"
       * xmlns:xlink="http://www.w3.org/1999/xlink"
       * xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       * office:version="1.2">
       * */
      if(qualifiedName().toString() == "office:document-content")
        {
          //<office:body>

          //<note type="input" label="output, histogram column width">30</note>
          while(readNextStartElement())
            {
              qDebug() << qualifiedName();
              if(qualifiedName().toString() == "office:body")
                {

                  //<office:spreadsheet>
                  while(readNextStartElement())
                    {
                      qDebug() << qualifiedName();
                      if(qualifiedName().toString() == "office:spreadsheet")
                        {
                          //<table:table table:name="classeur"
                          // table:style-name="ta1" table:print="false">
                          qDebug() << qualifiedName();
                          readTable();
                        }
                      else
                        {
                          skipCurrentElement();
                        }
                    }
                }
              else
                {
                  skipCurrentElement();
                }
            }
        }
      else
        {
          raiseError(QObject::tr("Not an OASIS content XML"));
          skipCurrentElement();
        }
    }
  return !error();
}


bool
QXmlStreamReaderContentXml::readTable()
{

  qDebug() << qualifiedName();
  while(readNextStartElement())
    {

      qDebug() << qualifiedName();
      if(qualifiedName().toString() == "table:table")
        {
          QString spread_sheet_name =
            attributes().value("table:name").toString();
          if(spread_sheet_name.isEmpty())
            {
              //_errorStr = QObject::tr("spread_sheet_name is
              // empty.");
              // return false;
            }
          m_odsReader.startSheet(spread_sheet_name);

          readTableRow();
        }
      else
        {
          // raiseError(QObject::tr("Not an OASIS content XML"));
          skipCurrentElement();
        }
    }

  return !error();
}


bool
QXmlStreamReaderContentXml::readTableRow()
{

  //<table:table-row table:style-name="ro1">
  qDebug() << qualifiedName();
  while(readNextStartElement())
    {

      qDebug() << qualifiedName();
      if(qualifiedName().toString() == "table:table-row")
        {
          m_odsReader.startLine();
          readTableLine();
          m_odsReader.endLine();
        }
      else
        {
          // raiseError(QObject::tr("Not an OASIS content XML"));
          skipCurrentElement();
        }
    }

  return !error();
}


bool
QXmlStreamReaderContentXml::readTableLine()
{

  //<table:table-cell office:value-type="string" table:style-name="ce1">
  //              <text:p>truc</text:p>
  //                 </table:table-cell>
  qDebug() << qualifiedName();
  while(readNextStartElement())
    {

      qDebug() << qualifiedName();
      if(qualifiedName().toString() == "table:table-cell")
        {

          m_numberColumnsRepeated = 1;
          m_currentCell.setOfficeValueType(
            attributes().value("office:value-type").toString());
          if(m_currentCell.getOfficeValueType().isEmpty())
            {
              m_currentCell.setOfficeValueType(
                attributes().value("calcext:value-type").toString());
            }


          // table:number-columns-repeated="2"
          // <table:table-cell table:number-columns-repeated="2"
          // office:value-type="string"><text:p>N.A.</text:p></table:table-cell>

          if(!attributes()
                .value("table:number-columns-repeated")
                .toString()
                .isEmpty())
            {
              m_numberColumnsRepeated =
                attributes().value("table:number-columns-repeated").toUInt();
              // System.out.println("coucou " + numberColumnsRepeated);
            }

          if(!m_currentCell.getOfficeValueType().isEmpty())
            {

              QString dateStr =
                attributes().value("office:date-value").toString();
              if(!dateStr.isEmpty())
                {
                  // qDebug() << "dateStr " << dateStr;
                  QDateTime date(QDateTime::fromString(dateStr, Qt::ISODate));
                  // date.fromString(dateStr,Qt::ISODate);
                  // qDebug() << " date.fromString " <<
                  // date.toString(Qt::ISODate);
                  m_currentCell.setDateValue(date);
                }


              if(m_currentCell.getOfficeValueType() == "float")
                {
                  /*
                   * writer.writeAttribute("office",
                   * hashNamespaceURI.get("office"), "value-type",
                   * "float"); writer.writeAttribute("office",
                   * hashNamespaceURI.get("office"), "value", value);
                   */
                  QString valueStr =
                    attributes().value("office:value").toString();
                  if(valueStr.isEmpty())
                    {
                      raiseError(QObject::tr("office:value is null"));
                    }
                  m_currentCell.setValueDouble(valueStr.toDouble());
                }
              else if(m_currentCell.getOfficeValueType() == "boolean")
                {
                  // office:boolean-value="false" calcext:value-type="boolean"
                  // office:value-type="boolean"
                  QString valueStr =
                    attributes().value("office:boolean-value").toString();
                  m_currentCell.setValueBoolean(false);
                  if(valueStr.isEmpty())
                    {
                      m_currentCell.setValueBoolean(false);
                    }
                  else if(valueStr == "true")
                    {
                      m_currentCell.setValueBoolean(true);
                    }
                }
            }

          // content cell

          readCellContent();

          // skipCurrentElement();

          // end table cell
          while(m_numberColumnsRepeated > 0)
            {
              m_odsReader.setInsideCell(m_currentCell);
              m_numberColumnsRepeated--;
            }
        }


      else
        {
          // raiseError(QObject::tr("Not an OASIS content XML"));
          skipCurrentElement();
        }
    }

  return !error();
}


bool
QXmlStreamReaderContentXml::readCellContent()
{

  while(readNextStartElement())
    {

      qDebug() << qualifiedName();
      if(qualifiedName().toString() == "office:annotation")
        {
          //dc:date
          skipCurrentElement();
        }
      else if(qualifiedName().toString() == "text:p")
        {
          readTextP();
        }
      else
        {
          raiseError(
            QObject::tr("Not an OASIS content XML %1").arg(qualifiedName()));
        }
    }


  return !error();
}


bool
QXmlStreamReaderContentXml::readTextP()
{
  m_currentCell._string_value.append(
    readElementText(QXmlStreamReader::IncludeChildElements));

  return !error();
}
