
#include <catch2/catch_test_macros.hpp>

#include <QDebug>

#include <pappsomspp/trace/datapoint.h>
#include <pappsomspp/trace/trace.h>
#include <pappsomspp/trace/maptrace.h>
#include <pappsomspp/massspectrum/massspectrum.h>

using namespace pappso;


TEST_CASE("Constructing MassSpectrum objects.", "[MapSpectrum][constructors]")
{
  // Create a MassSpectrum that looks like something real.

  std::vector<DataPoint> data_point_vector;

  // clang-format off
  data_point_vector.push_back(DataPoint("610.02000 12963.5715942383"));
  data_point_vector.push_back(DataPoint("610.07000 15639.6568298340"));
  data_point_vector.push_back(DataPoint("610.12000 55999.7628784180"));
  data_point_vector.push_back(DataPoint("610.17000 9335990.3578681946"));
  data_point_vector.push_back(DataPoint("610.2200000 635674266.1611375809"));
  data_point_vector.push_back(DataPoint("610.27000 54459.4762458801"));
  data_point_vector.push_back(DataPoint("610.32000 205580.6580276489"));
  data_point_vector.push_back(DataPoint("610.37000 84627.3196716309"));
  data_point_vector.push_back(DataPoint("610.42000 51061.7636718750"));
  data_point_vector.push_back(DataPoint("610.47000 20260.0218505859"));
  data_point_vector.push_back(DataPoint("610.52000 29848.3424072266"));
  data_point_vector.push_back(DataPoint("610.57000 27266.8031616211"));
  data_point_vector.push_back(DataPoint("610.62000 36922.3937377930"));
  data_point_vector.push_back(DataPoint("610.67000 44082.4265441895"));
  data_point_vector.push_back(DataPoint("610.72000 32580.1677703857"));
  data_point_vector.push_back(DataPoint("610.77000 39453.8380126953"));
  data_point_vector.push_back(DataPoint("610.82000 63698.7124328613"));
  data_point_vector.push_back(DataPoint("610.87000 34406.7755126953"));
  data_point_vector.push_back(DataPoint("610.92000 33385.7486267090"));
  data_point_vector.push_back(DataPoint("610.97000 22105.9357604980"));
  data_point_vector.push_back(DataPoint("611.02000 34175.9539184570"));
  data_point_vector.push_back(DataPoint("611.07000 18893.1743774414"));
  data_point_vector.push_back(DataPoint("611.12000 33655.8040771484"));
  data_point_vector.push_back(DataPoint("611.17000 1985432.9582707286"));
  data_point_vector.push_back(DataPoint("611.220000 350845489.9638078809"));
  data_point_vector.push_back(DataPoint("611.27000 201093.0304565430"));
  data_point_vector.push_back(DataPoint("611.32000 130582.0210266113"));
  data_point_vector.push_back(DataPoint("611.37000 191842.3922958374"));
  data_point_vector.push_back(DataPoint("611.42000 154248.7982788086"));
  data_point_vector.push_back(DataPoint("611.47000 31618.7268676758"));
  data_point_vector.push_back(DataPoint("611.52000 31222.7547607422"));
  data_point_vector.push_back(DataPoint("611.57000 44491.2401733398"));
  data_point_vector.push_back(DataPoint("611.62000 17576.1995697021"));
  data_point_vector.push_back(DataPoint("611.67000 29514.0727844238"));
  data_point_vector.push_back(DataPoint("611.72000 60104.3011474609"));
  data_point_vector.push_back(DataPoint("611.77000 54284.4918212891"));
  data_point_vector.push_back(DataPoint("611.82000 73222.5983886719"));
  data_point_vector.push_back(DataPoint("611.87000 34145.2793884277"));
  data_point_vector.push_back(DataPoint("611.92000 43328.2853698730"));
  data_point_vector.push_back(DataPoint("611.97000 34486.0655212402"));
  data_point_vector.push_back(DataPoint("612.02000 33462.5801696777"));
  data_point_vector.push_back(DataPoint("612.07000 45740.2189331055"));
  data_point_vector.push_back(DataPoint("612.12000 16315.6034545898"));
  data_point_vector.push_back(DataPoint("612.17000 3137434.1922011375"));
  data_point_vector.push_back(DataPoint("612.220000 244825577.0747365952"));
  data_point_vector.push_back(DataPoint("612.27000 107560.2426452637"));
  data_point_vector.push_back(DataPoint("612.32000 114637.8828430176"));
  data_point_vector.push_back(DataPoint("612.37000 87648.2245483398"));
  data_point_vector.push_back(DataPoint("612.42000 75788.5508422852"));
  data_point_vector.push_back(DataPoint("612.47000 33858.1067199707"));
  data_point_vector.push_back(DataPoint("612.52000 26404.7212524414"));
  data_point_vector.push_back(DataPoint("612.57000 45710.7806396484"));
  data_point_vector.push_back(DataPoint("612.62000 31294.2814941406"));
  data_point_vector.push_back(DataPoint("612.67000 29457.2803955078"));
  data_point_vector.push_back(DataPoint("612.72000 23048.1495971680"));
  data_point_vector.push_back(DataPoint("612.77000 15255.7875061035"));
  data_point_vector.push_back(DataPoint("612.82000 48801.3896789551"));
  data_point_vector.push_back(DataPoint("612.87000 36464.7495727539"));
  data_point_vector.push_back(DataPoint("612.92000 51507.2986145020"));
  data_point_vector.push_back(DataPoint("612.97000 45925.2813415527"));
  data_point_vector.push_back(DataPoint("613.02000 40396.0013732910"));
  data_point_vector.push_back(DataPoint("613.07000 40331.5417785645"));
  data_point_vector.push_back(DataPoint("613.12000 47593.1001892090"));
  data_point_vector.push_back(DataPoint("613.17000 1537602.4452308416"));
  data_point_vector.push_back(DataPoint("613.22000 95458729.2017828822"));
  data_point_vector.push_back(DataPoint("613.27000 117836.8993530273"));
  data_point_vector.push_back(DataPoint("613.32000 172388.2191467285"));
  data_point_vector.push_back(DataPoint("613.37000 117651.7643432617"));
  data_point_vector.push_back(DataPoint("613.42000 134527.9219970703"));
  data_point_vector.push_back(DataPoint("613.47000 21348.3722229004"));
  data_point_vector.push_back(DataPoint("613.52000 480.5255737305"));
  data_point_vector.push_back(DataPoint("613.57000 71578.8419189453"));
  data_point_vector.push_back(DataPoint("613.62000 47088.4295806885"));
  data_point_vector.push_back(DataPoint("613.67000 11516.1672668457"));
  data_point_vector.push_back(DataPoint("613.72000 42134.2611389160"));
  data_point_vector.push_back(DataPoint("613.77000 43366.3011627197"));
  data_point_vector.push_back(DataPoint("613.82000 76272.4001235962"));
  data_point_vector.push_back(DataPoint("613.87000 98113.1940002441"));
  data_point_vector.push_back(DataPoint("613.92000 29165.7173461914"));
  data_point_vector.push_back(DataPoint("613.97000 55852.7840881348"));
  data_point_vector.push_back(DataPoint("614.02000 29957.4020996094"));
  data_point_vector.push_back(DataPoint("614.07000 46380.1217651367"));
  data_point_vector.push_back(DataPoint("614.12000 22395.2603759766"));
  data_point_vector.push_back(DataPoint("614.17000 1585080.8988181949"));
  data_point_vector.push_back(DataPoint("614.22000 35239172.4581222534"));
  data_point_vector.push_back(DataPoint("614.27000 185695.5917358398"));
  data_point_vector.push_back(DataPoint("614.32000 231630.3202667236"));
  data_point_vector.push_back(DataPoint("614.37000 165712.7152709961"));
  data_point_vector.push_back(DataPoint("614.42000 115771.4071350098"));
  data_point_vector.push_back(DataPoint("614.47000 58982.7239074707"));
  data_point_vector.push_back(DataPoint("614.52000 2547873.7498645782"));
  data_point_vector.push_back(DataPoint("614.57000 18437.3129577637"));
  data_point_vector.push_back(DataPoint("614.62000 22860.9023132324"));
  data_point_vector.push_back(DataPoint("614.67000 21072.2604064941"));
  data_point_vector.push_back(DataPoint("614.72000 35379.6509933472"));
  data_point_vector.push_back(DataPoint("614.77000 59054.2345886230"));
  data_point_vector.push_back(DataPoint("614.82000 75995.3719787598"));
  data_point_vector.push_back(DataPoint("614.87000 106325.3341369629"));
  data_point_vector.push_back(DataPoint("614.92000 43670.2942276001"));
  data_point_vector.push_back(DataPoint("614.97000 39008.6439514160"));
  // clang-format on

  REQUIRE(100 == data_point_vector.size());

  // Create a Trace using the DataPoint vector.
  Trace trace(data_point_vector);
  REQUIRE(100 == trace.size());

  SECTION("Create a MassSpectrum from a Trace", "[MassSpectrum]")
  {
    MassSpectrum mass_spectrum(trace);

    REQUIRE(100 == mass_spectrum.size());
    REQUIRE(mass_spectrum.front().x == 610.02000);
    REQUIRE(mass_spectrum.front().y == 12963.5715942383);
    REQUIRE(mass_spectrum.back().x == 614.97000);
    REQUIRE(mass_spectrum.back().y == 39008.6439514160);
  }

  SECTION("Create a MassSpectrum from a MapTrace", "[MassSpectrum]")
  {
    // Create a MapTrace
    MapTrace map_trace(trace);
    REQUIRE(100 == map_trace.size());

    MassSpectrum mass_spectrum(map_trace);

    REQUIRE(100 == mass_spectrum.size());
    REQUIRE(mass_spectrum.front().x == 610.02000);
    REQUIRE(mass_spectrum.front().y == 12963.5715942383);
    REQUIRE(mass_spectrum.back().x == 614.97000);
    REQUIRE(mass_spectrum.back().y == 39008.6439514160);
  }

  SECTION("Create a MassSpectrum from a vector of double pairs",
          "[MassSpectrum]")
  {
    std::vector<std::pair<pappso_double, pappso_double>> double_pair_vector{
      std::pair<double, double>(610.02000, 12963.5715942383),
      std::pair<double, double>(610.07000, 15639.6568298340),
      std::pair<double, double>(610.12000, 55999.7628784180)};

    MassSpectrum mass_spectrum(double_pair_vector);

    REQUIRE(3 == mass_spectrum.size());
    REQUIRE(mass_spectrum.front().x == 610.02000);
    REQUIRE(mass_spectrum.front().y == 12963.5715942383);
    REQUIRE(mass_spectrum.back().x == 610.12000);
    REQUIRE(mass_spectrum.back().y == 55999.7628784180);
  }

  SECTION("Create a MassSpectrum from another MassSpectrum", "[MassSpectrum]")
  {
    MassSpectrum mass_spectrum(trace);

    MassSpectrum mass_spectrum1(mass_spectrum);

    REQUIRE(100 == mass_spectrum1.size());
    REQUIRE(mass_spectrum1.front().x == 610.02000);
    REQUIRE(mass_spectrum1.front().y == 12963.5715942383);
    REQUIRE(mass_spectrum1.back().x == 614.97000);
    REQUIRE(mass_spectrum1.back().y == 39008.6439514160);
  }

  SECTION("Initialize MassSpectrum with operator =", "[MassSpectrum]")
  {
    MassSpectrum mass_spectrum(trace);
    MassSpectrum mass_spectrum1;
    mass_spectrum1 = mass_spectrum;

    REQUIRE(100 == mass_spectrum1.size());
    REQUIRE(mass_spectrum1.front().x == 610.02000);
    REQUIRE(mass_spectrum1.front().y == 12963.5715942383);
    REQUIRE(mass_spectrum1.back().x == 614.97000);
    REQUIRE(mass_spectrum1.back().y == 39008.6439514160);
  }
}

TEST_CASE("Basic functionality of MassSpectrum", "[MassSpectrum]")
{
  std::vector<std::pair<pappso_double, pappso_double>> double_pair_vector{
    std::pair<double, double>(610.02000, 12963.5715942383),
    std::pair<double, double>(610.07000, 15639.6568298340),
    std::pair<double, double>(610.12000, 55999.7628784180)};

  MassSpectrum mass_spectrum(double_pair_vector);

  SECTION("Compute TIC for MassSpectrum", "[MassSpectrum]")
  {
    double tic = mass_spectrum.totalIonCurrent();
    REQUIRE(tic == 12963.5715942383 + 15639.6568298340 + 55999.7628784180);

    tic = mass_spectrum.tic();
    REQUIRE(tic == 12963.5715942383 + 15639.6568298340 + 55999.7628784180);

    tic = mass_spectrum.tic(610.020001, 610.12001);
    REQUIRE(tic == 15639.6568298340 + 55999.7628784180);
  }

  SECTION("Get the maxIntensityDataPoint from MassSpectrum", "[MassSpectrum]")
  {
    DataPoint datapoint = mass_spectrum.maxIntensityDataPoint();
    REQUIRE(datapoint.x == 610.1200000);
    REQUIRE(datapoint.y == 55999.7628784180);
  }

  SECTION("Get the minIntensityDataPoint from MassSpectrum", "[MassSpectrum]")
  {
    DataPoint datapoint = mass_spectrum.minIntensityDataPoint();
    REQUIRE(datapoint.x == 610.02000);
    REQUIRE(datapoint.y == 12963.5715942383);
  }
}
