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


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


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


/////////////////////// Catch2 includes
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>


/////////////////////// Local includes
#include "tests-config.h"
#include "TestUtils.hpp"
#include "MsXpS/libXpertMassCore/globals.hpp"
#include "MsXpS/libXpertMassCore/Polymer.hpp"
#include "MsXpS/libXpertMassCore/CrossLink.hpp"
#include "MsXpS/libXpertMassCore/CrossLinkedRegion.hpp"

namespace MsXpS
{
namespace libXpertMassCore
{
TestUtils test_utils_1_letter_cross_linked_region("protein-1-letter", 1);

ErrorList error_list_cross_linked_region;

SCENARIO("Construction of an empty CrossLinkedRegion", "[CrossLinkedRegion]")
{
  CrossLinkedRegion cross_linked_region;
}


SCENARIO("Construction of a CrossLinkedRegion with indices",
         "[CrossLinkedRegion]")
{
  WHEN("Allocating a CrossLinkedRegion with indices")
  {
    CrossLinkedRegion cross_linked_region(100, 120);

    THEN("The member data are set accordingly")
    {
      REQUIRE(cross_linked_region.getStartIndex() == 100);
      REQUIRE(cross_linked_region.getStopIndex() == 120);

      REQUIRE(cross_linked_region.getCrossLinksRef().size() == 0);
      REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 0);
    }
  }
}

SCENARIO(
  "Construction of an empty CrossLinkedRegion and setting indices with setters",
  "[CrossLinkedRegion]")
{
  WHEN("Allocating a CrossLinkedRegion with indices")
  {
    CrossLinkedRegion cross_linked_region;
    cross_linked_region.setStartIndex(100);
    cross_linked_region.setStopIndex(120);

    THEN("The member data are set accordingly")
    {
      REQUIRE(cross_linked_region.getStartIndex() == 100);
      REQUIRE(cross_linked_region.getStopIndex() == 120);

      REQUIRE(cross_linked_region.getCrossLinksRef().size() == 0);
      REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 0);
    }
  }
}

SCENARIO(
  "Construction of an empty CrossLinkedRegion and adding CrossLink instances",
  "[CrossLinkedRegion]")
{
  GIVEN("CrossLink instances")
  {
    test_utils_1_letter_cross_linked_region.initializeXpertmassLibrary();

    PolChemDefCstSPtr pol_chem_def_csp =
      test_utils_1_letter_cross_linked_region.msp_polChemDef;

    QString polymer_file_path =
      QString("%1/polymer-sequences/%2")
        .arg(TESTS_INPUT_DIR)
        .arg("cyan-fluorescent-protein-no-cross-link.mxp");

    PolymerQSPtr polymer_sp = Polymer::createSPtr(pol_chem_def_csp);
    REQUIRE(polymer_sp->renderXmlPolymerFile(polymer_file_path));
    REQUIRE(polymer_sp->size() == 240);

    CrossLinkSPtr cross_link_1_sp =
      std::make_shared<CrossLink>(pol_chem_def_csp,
                                  polymer_sp,
                                  "CFP-chromophore",
                                  "-H2OH2",
                                  "This is a comment for cross-link 1");


    CrossLinkSPtr cross_link_2_sp =
      std::make_shared<CrossLink>(pol_chem_def_csp,
                                  polymer_sp,
                                  "CFP-chromophore",
                                  "-H2OH2",
                                  "This is a comment for cross-link 2");

    CrossLinkSPtr cross_link_3_sp =
      std::make_shared<CrossLink>(pol_chem_def_csp,
                                  polymer_sp,
                                  "CFP-chromophore",
                                  "-H2OH2",
                                  "This is a comment for cross-link 3");

    std::vector<CrossLinkSPtr> cross_links;
    cross_links.push_back(cross_link_2_sp);
    cross_links.push_back(cross_link_3_sp);

    AND_GIVEN("A CrossLinkedRegion allocated with indices")
    {
      CrossLinkedRegion cross_linked_region(100, 120);

      THEN("The member data are set accordingly")
      {
        REQUIRE(cross_linked_region.getStartIndex() == 100);
        REQUIRE(cross_linked_region.getStopIndex() == 120);

        REQUIRE(cross_linked_region.getCrossLinksRef().size() == 0);
        REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 0);
      }

      WHEN(
        "New CrossLink instances are added, these are stored in the "
        "CrossLinkedRegion")
      {
        cross_linked_region.appendCrossLink(cross_link_1_sp);
        REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 1);

         cross_linked_region.appendCrossLinks(cross_links);
        REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 3);

        AND_WHEN(
          "CrossLink instances are remove, these disappear from the "
          "CrossLinkedRegion")
        {
          cross_linked_region.removeCrossLink(cross_link_1_sp);
          REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 2);
          REQUIRE(cross_linked_region.getCrossLinksCstRef()
                    .front()
                    ->getComment()
                    .toStdString() == "This is a comment for cross-link 2");

          cross_linked_region.removeCrossLinkAt(0);
          REQUIRE(cross_linked_region.getCrossLinksCstRef().size() == 1);
          REQUIRE(cross_linked_region.getCrossLinksCstRef()
                    .front()
                    ->getComment()
                    .toStdString() == "This is a comment for cross-link 3");
        }
      }
    }
  }
}


} // namespace libXpertMassCore
} // namespace MsXpS
