// ./tests/catch2-tests [section] -s


/////////////////////// Qt includes
#include <QDebug>
#include <QString>
#include <QDir>


/////////////////////// IsoSpec
#include <IsoSpec++/isoSpec++.h>
#include <IsoSpec++/element_tables.h>


/////////////////////// Catch2 includes
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>


/////////////////////// libXpertMassCore includes
#include "MsXpS/libXpertMassCore/Isotope.hpp"
#include "MsXpS/libXpertMassCore/IsotopicData.hpp"
#include "MsXpS/libXpertMassCore/IsotopicDataLibraryHandler.hpp"


/////////////////////// Local includes
#include "tests-config.h"
#include "TestUtils.hpp"


namespace MsXpS
{
namespace libXpertMassCore
{


SCENARIO("IsotopicDataLibraryHandler loads data from IsoSpec++'s tables",
         "[IsotopicDataLibraryHandler]")
{
  TestUtils test_utils;

  test_utils.initializeXpertmassLibrary();

  IsotopicDataLibraryHandler isotopic_data_lib_handler;

  WHEN("Constructed, the data are empty")
  {
    THEN("The isotopic data are empty but they are allocated")
    {
      REQUIRE(isotopic_data_lib_handler.getIsotopicData() != nullptr);
    }

    AND_WHEN("The file name is set by the setter (although not used here)")
    {
      isotopic_data_lib_handler.setFileName("the_file_name.dat");

      THEN("The getter returns the proper file name (although not used here)")
      {
        REQUIRE(isotopic_data_lib_handler.getFileName().toStdString() ==
                "the_file_name.dat");
      }
    }
  }

  AND_WHEN("Loading isotopic data from library")
  {
    qsizetype count_non_isotope_skipped_items = 0;
    qsizetype loaded_isotope_count =
      isotopic_data_lib_handler.loadData(count_non_isotope_skipped_items);

    THEN("The number of isotopes loaded is checked")
    {
      REQUIRE(loaded_isotope_count + count_non_isotope_skipped_items ==
              IsoSpec::isospec_number_of_isotopic_entries);
      REQUIRE(isotopic_data_lib_handler.getIsotopicData()->size() ==
              loaded_isotope_count);
    }
  }

  AND_WHEN("A new IsotopicDataLibraryHandler instance is copy constructed")
  {
    long use_count_before_copy =
      isotopic_data_lib_handler.getIsotopicData().use_count();

    IsotopicDataLibraryHandler isotopic_data_lib_handler_1(
      isotopic_data_lib_handler);

    THEN("The instances are checked and should be identical")
    {
      REQUIRE(isotopic_data_lib_handler.getIsotopicData()->size() ==
              isotopic_data_lib_handler_1.getIsotopicData()->size());

      long use_count_after_copy =
        isotopic_data_lib_handler.getIsotopicData().use_count();

      REQUIRE(use_count_after_copy == use_count_before_copy + 1);
    }
  }
}

SCENARIO("IsotopicDataLibraryHandler writes data to file",
         "[IsotopicDataLibraryHandler]")
{
  IsotopicDataLibraryHandler isotopic_data_lib_handler;

  WHEN("Data have been loaded, the data are checked")
  {
    qsizetype non_isotope_skipped_items = 0;
    qsizetype loaded_isotope_count =
      isotopic_data_lib_handler.loadData(non_isotope_skipped_items);

    THEN("The number of isotopes loaded is checked")
    {
      REQUIRE(loaded_isotope_count + non_isotope_skipped_items ==
              IsoSpec::isospec_number_of_isotopic_entries);
      REQUIRE(isotopic_data_lib_handler.getIsotopicData()->size() ==
              loaded_isotope_count);
    }

    AND_WHEN("Isotopic data are written to file")
    {
      QString isotopes_output_dir =
        QString("%1/%2").arg(TESTS_OUTPUT_DIR).arg("isotopes");

      QDir dir;
      bool result = dir.mkpath(isotopes_output_dir);
      REQUIRE(result == true);

      QString output_file_name =
        QString("%1/%2").arg(isotopes_output_dir).arg("isospec-tables.dat");

      // qDebug()  << "The write file name: " << output_file_name.toStdString()
      // << std::endl;

      std::size_t written_isotope_count =
        isotopic_data_lib_handler.writeData(output_file_name);

      THEN("The count of written isotopes is checked")
      {
        REQUIRE(written_isotope_count == loaded_isotope_count);
      }
    }
  }
}


} // namespace libXpertMassCore
} // namespace MsXpS
