#include "bandit/bandit/bandit.h"
#include "../../src/cdo_options.h"
// BANDIT NEEDS TO BE INCLUDED FIRST!!!

#include "../../src/util_string.h"
#include <string>
#include <tuple>

using namespace snowhouse;
void
cdoExit()
{
}
go_bandit([]() {
  //==============================================================================

  bandit::describe(
      "Testing function 'tokenize_comma_seperated_int_list'", []() {
        bandit::describe("Testing tokenization with proper input", []() {
          std::string to_be_tokenized{ "1,-2,3,4" };
          std::vector<std::string> expected_tokens = { "1", "-2", "3", "4" };
          std::tuple<bool, std::vector<std::string>> result
              = tokenize_comma_seperated_int_list(to_be_tokenized);
          bandit::it("returns true on success",
                     [&]() { AssertThat(std::get<0>(result), Equals(true)); });
          bandit::it("returns the right tokens", [&]() {
            AssertThat(std::get<1>(result), EqualsContainer(expected_tokens));
          });
        });

        bandit::describe(
            "Testing tokenization with input containing non int", []() {
              std::vector<std::string> expected_tokens = {};
              std::string to_be_tokenized{ "1,a,3,4" };
              std::tuple<bool, std::vector<std::string>> result
                  = tokenize_comma_seperated_int_list(to_be_tokenized);

              bandit::it("returns false on failure", [&]() {
                AssertThat(std::get<0>(result), Equals(false));
              });
              bandit::it("returns a empty list", [&]() {
                AssertThat(std::get<1>(result),
                           EqualsContainer(expected_tokens));
              });
            });
        bandit::describe(
            "Testing tokenization with input containing a float value", []() {
              std::vector<std::string> expected_tokens = {};
              std::string to_be_tokenized{ "1,1.2,3" };
              std::tuple<bool, std::vector<std::string>> result
                  = tokenize_comma_seperated_int_list(to_be_tokenized);

              bandit::it("returns false", [&]() {
                AssertThat(std::get<0>(result), Equals(false));
              });
              bandit::it("returns empty list", [&]() {
                AssertThat(std::get<1>(result),
                           EqualsContainer(expected_tokens));
              });
            });
        bandit::describe(
            "Testing tokenization with input containing a single value", []() {
              std::vector<std::string> expected_tokens = { "1" };
              std::string to_be_tokenized{ "1" };
              std::tuple<bool, std::vector<std::string>> result
                  = tokenize_comma_seperated_int_list(to_be_tokenized);

              bandit::it("returns true", [&]() {
                AssertThat(std::get<0>(result), Equals(true));
              });
              bandit::it("returns the token  '1'", [&]() {
                AssertThat(std::get<1>(result),
                           EqualsContainer(expected_tokens));
              });
            });
        bandit::describe("Testing trim functions", []() {
          bandit::describe("Testing ltrim function", []() {
            std::string to_be_trimmed = "  spaces in front  ";
            std::string expected = "spaces in front  ";
            bandit::it("returns the right trim", [&]() {
              std::string result = Util::String::ltrim(to_be_trimmed);
              AssertThat(result, Equals(expected));
            });
          });
          bandit::describe("Testing rtrim function", []() {
            std::string to_be_trimmed = "  spaces in back  ";
            std::string expected = "  spaces in back";
            bandit::it("returns the right trim", [&]() {
              std::string result = Util::String::rtrim(to_be_trimmed);
              AssertThat(result, Equals(expected));
            });
          });
          bandit::describe("Testing trim function", []() {
            std::string to_be_trimmed = "  no spaces  ";
            std::string expected = "no spaces";
            bandit::it("returns the right trim", [&]() {
              std::string result = Util::String::trim(to_be_trimmed);
              AssertThat(result, Equals(expected));
            });
          });
        });
      });

  bandit::describe("Testing function 'split_args'", []() {
    bandit::it("splits simple arguments", []() {
      std::string test_args = "abc,def,ghi";
      std::vector<std::string> expected = { "abc", "def", "ghi" };
      std::vector<std::string> result = split_args(test_args);
      AssertThat(result, EqualsContainer(expected));
    });
    bandit::it("allows for ',' to be escaped and removes the '\\'", []() {
      std::string test_args = "abc,\"def\\,ghi\",jkl";
      std::vector<std::string> expected = { "abc", "\"def,ghi\"", "jkl" };
      std::vector<std::string> result = split_args(test_args);
      AssertThat(result, EqualsContainer(expected));
    });
   bandit::it("handles leftover ' correctly", []() {
      std::string test_args = "abc,";
      AssertThrows(std::runtime_error,split_args(test_args));
    });

  });
});
int
main(int argc, char **argv)
{
  int result = bandit::run(argc, argv);

  return result;
}
