#include <catch2/catch.hpp>
#include "schneide_base/CSVReader.hpp"

using namespace schneide;

TEST_CASE("can parse a line of separated values")
{
  auto parsed = CSVReader::parseString("easy,for,rtz");
  REQUIRE(parsed.size() == 1);
  auto const& line = parsed.back();
  REQUIRE(line == CSVReader::valuesFor({"easy", "for", "rtz"}));
}

TEST_CASE("can parse separate lines")
{
  auto const runWith = [](std::string const& content) {
    auto parsed = CSVReader::parseString(content);

    REQUIRE(parsed.size() == 2);
    REQUIRE(parsed.at(0) == CSVReader::valuesFor({"a", "b"}));
    REQUIRE(parsed.at(1) == CSVReader::valuesFor({"c", "d"}));
  };

  SECTION("with just LF")
  {
    runWith("a,b\nc,d");
  }

  SECTION("with CRLF")
  {
    runWith("a,b\r\nc,d");
  }
}

TEST_CASE("can parse doubles")
{
  auto parsed = CSVReader::parseString("1.0, 2.0\n3.0,  6.0\n4.0, 4.5");
  REQUIRE(parsed.at(0).at(0).asDouble() == 1.0);
  REQUIRE(parsed.at(0).at(1).asDouble() == 2.0);
  REQUIRE(parsed.at(1).at(0).asDouble() == 3.0);
  REQUIRE(parsed.at(1).at(1).asDouble() == 6.0);
  REQUIRE(parsed.at(2).at(0).asDouble() == 4.0);
  REQUIRE(parsed.at(2).at(1).asDouble() == 4.5);
}

TEST_CASE("empty creates no lines")
{
  auto parsed = CSVReader::parseString("");
  REQUIRE(parsed.empty());
}

TEST_CASE("empty line is ignored")
{
  auto parsed = CSVReader::parseString("a,b\n");
  REQUIRE(parsed.size() == 1);
}

TEST_CASE("throws on incomplete parse")
{
  REQUIRE_THROWS(CSVReader::parseString("3;1").at(0).at(0).asDouble());
}

TEST_CASE("can read CSV spectrums")
{
  auto data = R"_(Wavenumber;Null;Sample;Difference;Smoothed
4000.00;1;1;0;0
3600.00;1;1;0;0
3200.00;1;1;0;0
2800.00;1;1;0;0
2400.00;1;1;0;0
2000.00;1;1;0;0
1600.00;1;1;0;0
1200.00;1;1;0;0
800.00;1;1;0;0
400.00;1;1;0;0)_";

  auto parsed = CSVReader::parseString(data, ';');
  REQUIRE(parsed.size() == 11);
  for (auto const& line : parsed)
    REQUIRE(line.size() == 5);

  REQUIRE(parsed.at(0).at(2).asString() == "Sample");
  REQUIRE(parsed.at(3).at(0).asString() == "3200.00");
  REQUIRE(parsed.at(10).at(4).asDouble() == 0.0);
}
