
#include <catch2/catch_test_macros.hpp>

#include "config.h"
#include <QDebug>
#include <iostream>
#include <odsstream/calcwriterinterface.h>
#include <odsstream/odsdocwriter.h>
#include <odsstream/odsdocreader.h>
#include <odsstream/odsdocwriter.h>
#include <odsstream/odsexception.h>
#include <odsstream/writer/options/odscolorscale.h>
#include <odsstream/writer/options/odstablecellstyle.h>
#include "metadataodsreader.h"
#include <QVariant>


// make test ARGS="-V -I 1,1"

// ./test/test_ods [ods] -s

using namespace std;

class CustomHandler : public OdsDocHandlerInterface
{
  public:
  /**
   * callback that indicates the begining of a data sheet. Override it in
   * order to retrieve information about the current data sheet.
   *
   */
  virtual void startSheet([[maybe_unused]] const QString &sheet_name){};

  /**
   * callback that indicates the end of the current data sheet. Override it if
   * needed
   */
  virtual void
  endSheet() override
  {
    qDebug() << "endSheet";
  };

  /**
   * callback that indicates a new line start. Override it if needed.
   */

  virtual void startLine() override{};

  /**
   * callback that indicates a line ending. Override it if needed.
   */

  virtual void endLine() override{};

  /**
   * callback that report the content of the current cell in a dedicated Cell
   * object. Override it if you need to retrieve cell content.
   */
  virtual void
  setCell(const OdsCell &cell) override
  {
    qDebug() << cell.toString();
  };

  /**
   * callback that report the end of the ODS document. Override it if you need
   * to know that reading is finished.
   */
  virtual void endDocument() override{};
};


class CustomHandlerXic : public OdsDocHandlerInterface
{
  public:
  /**
   * callback that indicates the begining of a data sheet. Override it in
   * order to retrieve information about the current data sheet.
   *
   */
  virtual void
  startSheet([[maybe_unused]] const QString &sheet_name)
  {
    m_columnNumber = 0;
    m_rowNumber    = 0;
    if((sheet_name == "Feuille1") || (sheet_name == "metadata"))
      {
      }
    else
      {
        throw OdsException(
          QObject::tr("sheet_name %1 != Feuille1").arg(sheet_name));
      }
  };

  /**
   * callback that indicates the end of the current data sheet. Override it if
   * needed
   */
  virtual void
  endSheet() override
  {
    qDebug() << "endSheet";
  };

  /**
   * callback that indicates a new line start. Override it if needed.
   */

  virtual void
  startLine() override
  {
    m_columnNumber = 0;
  };

  /**
   * callback that indicates a line ending. Override it if needed.
   */

  virtual void
  endLine() override
  {
    m_rowNumber++;
  };

  /**
   * callback that report the content of the current cell in a dedicated Cell
   * object. Override it if you need to retrieve cell content.
   */
  virtual void
  setCell(const OdsCell &cell) override
  {
    qDebug() << cell.toString();
    if((m_columnNumber == 0) && (m_rowNumber == 0) && (cell.toString() != "rt"))
      {
        throw OdsException(
          QObject::tr("cell.toString() %1 != rt").arg(cell.toString()));
      }
    if((m_rowNumber == 0) && (m_columnNumber == 1) &&
       (cell.toString() != "intensity"))
      {
        throw OdsException(
          QObject::tr("cell.toString() %1 != intensity").arg(cell.toString()));
      }
    if((m_rowNumber > 0) && (m_columnNumber == 0) &&
       (cell.getDoubleValue() != m_rowNumber))
      {
        throw OdsException(
          QObject::tr("cell.getDoubleValue() %1 != m_rowNumber %2")
            .arg(cell.getDoubleValue())
            .arg(m_rowNumber));
      }
    if((m_rowNumber > 0) && (m_columnNumber == 1) &&
       (cell.getDoubleValue() != 0))
      {
        if((m_rowNumber == 12) && (cell.getDoubleValue() == 5))
          {
          }
        else if((m_rowNumber == 21) && (cell.getDoubleValue() == 18))
          {
          }
        else if((m_rowNumber == 22) && (cell.getDoubleValue() == 6))
          {
          }
        else if((m_rowNumber == 23) && (cell.getDoubleValue() == 3))
          {
          }
        else if((m_rowNumber == 30) && (cell.getDoubleValue() == 2))
          {
          }
        else
          {
            throw OdsException(
              QObject::tr("cell.getDoubleValue() %1 != 0 at line %2")
                .arg(cell.getDoubleValue())
                .arg(m_rowNumber));
          }
      }
    m_columnNumber++;
  };

  /**
   * callback that report the end of the ODS document. Override it if you need
   * to know that reading is finished.
   */
  virtual void endDocument() override{};

  private:
  std::size_t m_rowNumber    = 0;
  std::size_t m_columnNumber = 0;
};


TEST_CASE("Test ODS metadata bug files.", "[odsbug]")
{
  // Set the debugging message formatting pattern.
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));

  SECTION(
    "reading "
    "/gorgone/pappso/moulon/users/Olivier/20240131_proteobench/mcqr/"
    "metadata_template.ods",
    "[odsbug]")
  {
    cout << endl << "..:: Test ODS files ::.." << endl;

    cout << endl
         << "..:: read ODS file "
            "metadata_template.ods ::.."
         << endl;
    MetadataOdsReader handler;
    QFile xicfile(QString(CMAKE_SOURCE_DIR).append("/test/data/metadata_template.ods"));
    OdsDocReader xicfile_reader(handler);
    REQUIRE_NOTHROW(xicfile_reader.parse(&xicfile));

    xicfile.close();

    cout << endl << "..:: read ODS file xic.ods is OK ::.." << endl;
  }
}
TEST_CASE("Test ODS files.", "[ods]")
{
  // Set the debugging message formatting pattern.
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));

  SECTION("reading /test/data/xic.ods", "[ods]")
  {
    cout << endl << "..:: Test ODS files ::.." << endl;

    cout << endl << "..:: read ODS file xic.ods ::.." << endl;
    CustomHandlerXic handler;
    QFile xicfile(QString("../").append("/test/data/xic.ods"));
    OdsDocReader xicfile_reader(handler);
    REQUIRE_NOTHROW(xicfile_reader.parse(&xicfile));

    xicfile.close();

    cout << endl << "..:: read ODS file xic.ods is OK ::.." << endl;
  }
  SECTION("reading other ods", "[ods]")
  {

    QFile file("test.ods");
    // file.open(QIODevice::WriteOnly);
    OdsDocWriter writer(&file);

    QColor red("red");
    OdsTableCellStyle style;
    style.setBackgroundColor(QColor("yellow"));
    style.setTextColor(red);

    OdsTableCellStyleRef ref = writer.getTableCellStyleRef(style);

    QString test("truc");

    writer.writeSheet("classeur");

    OdsTableSettings settings;
    // settings.setHorizontalWindowSplit(4);
    settings.setVerticalSplit(1);
    writer.setCurrentOdsTableSettings(settings);

    writer.writeCell(test);
    // writer.clearTableCellStyleRef();
    writer.setTableCellStyleRef(ref);
    writer.writeLine();
    writer.writeEmptyCell();
    writer.setCellAnnotation("ceci est un commentaire n1");
    writer.writeCell("coucou");
    bool vf(0);
    writer.writeCell(vf);
    writer.clearTableCellStyleRef();
    writer.writeLine();
    writer.writeLine();
    writer.writeLine();
    writer.writeCell(1);
    QString start_position = writer.getOdsCellCoordinate();
    writer.writeCell(2);
    writer.writeCell(3);
    writer.writeCell(4);
    writer.writeCell(5);

    writer.writeLine();
    writer.writeCell(6);
    writer.writeCell(7);
    writer.writeCell(8);
    writer.writeCell(9);
    writer.writeCell(10);
    QString end_position;
    end_position = writer.getOdsCellCoordinate();

    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " "
             << end_position;
    OdsColorScale color_scale(start_position, end_position);
    writer.addColorScale(color_scale);

    writer.writeSheet("classeur2");

    writer.setCurrentOdsTableSettings(settings);

    writer.writeCell(test);
    // writer.clearTableCellStyleRef();
    writer.setTableCellStyleRef(ref);
    writer.writeLine();
    writer.writeEmptyCell();
    writer.setCellAnnotation("ceci est un commentaire n1");
    writer.writeCell("coucou");

    QVariant var(28.753423424);
    writer.writeCellVariant(var);

    QDateTime currentdate(QDateTime::currentDateTime());

    writer.setCellAnnotation("ceci est un commentaire sur une date");
    writer.writeCell(currentdate);

    writer.clearTableCellStyleRef();
    writer.writeLine();
    writer.writeEmptyCell();
    writer.setCellAnnotation("ceci est un commentaire");
    writer.writeCell("coucou");
    writer.writeCell(vf);
    writer.writeCell(currentdate);

    writer.writeCellPercentage(0.2);

    QUrl urltest("http://pappso.inra.fr/");
    writer.writeCell(urltest, "ceci est un lien");

    writer.writeSheet("test coordinates");

    QStringList list_coordinates;
    for(int i = 0; i < 200; i++)
      {
        writer.writeCell(i + 1);
        list_coordinates << writer.getOdsCellCoordinate();
      }
    writer.writeLine();
    for(const QString &coord : list_coordinates)
      {
        writer.writeCell(coord);
      }
    settings.setVerticalSplit(1);
    writer.setCurrentOdsTableSettings(settings);
    settings.setVerticalSplit(2);
    writer.setCurrentOdsTableSettings(settings);

    writer.close();

    file.close();

    // qDebug() << "coucou";
    CustomHandler handler;
    // file.open();
    OdsDocReader reader(handler);
    reader.parse(&file);
    file.close();

    QFile file2("test2.ods");
    OdsDocReader reader2(handler);
    reader2.parse(&file2);

    file2.close();

    // SUCCESS

    OdsDocWriter writerb("testbis.ods");
    writerb.writeCell("coucou");

    writerb.writeCell(urltest, "ceci est un lien");
  }
}
