/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */

#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>

#include <cm/string_view>

#include "cm_static_string_view.hxx"

#include "cmArgumentParser.h"

namespace {

struct Result
{
  bool Option1 = false;
  bool Option2 = false;

  std::string String1;
  std::string String2;

  std::vector<std::string> List1;
  std::vector<std::string> List2;
  std::vector<std::string> List3;

  std::vector<std::vector<std::string>> Multi1;
  std::vector<std::vector<std::string>> Multi2;
  std::vector<std::vector<std::string>> Multi3;
};

std::initializer_list<cm::string_view> const args = {
  /* clang-format off */
  "OPTION_1",                // option
  "STRING_1",                // string arg missing value
  "STRING_2", "foo", "bar",  // string arg + unparsed value
  "LIST_1",                  // list arg missing values
  "LIST_2", "foo", "bar",    // list arg with 2 elems
  "LIST_3", "bar",           // list arg ...
  "LIST_3", "foo",           // ... with continuation
  "MULTI_2",                 // multi list with 0 lists
  "MULTI_3", "foo", "bar",   // multi list with first list with two elems
  "MULTI_3", "bar", "foo",   // multi list with second list with two elems
  /* clang-format on */
};

bool verifyResult(Result const& result,
                  std::vector<std::string> const& unparsedArguments,
                  std::vector<std::string> const& keywordsMissingValue)
{
  static std::vector<std::string> const foobar = { "foo", "bar" };
  static std::vector<std::string> const barfoo = { "bar", "foo" };
  static std::vector<std::string> const missing = { "STRING_1", "LIST_1" };

#define ASSERT_TRUE(x)                                                        \
  do {                                                                        \
    if (!(x)) {                                                               \
      std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
      return false;                                                           \
    }                                                                         \
  } while (false)

  ASSERT_TRUE(result.Option1);
  ASSERT_TRUE(!result.Option2);

  ASSERT_TRUE(result.String1.empty());
  ASSERT_TRUE(result.String2 == "foo");

  ASSERT_TRUE(result.List1.empty());
  ASSERT_TRUE(result.List2 == foobar);
  ASSERT_TRUE(result.List3 == barfoo);

  ASSERT_TRUE(result.Multi1.empty());
  ASSERT_TRUE(result.Multi2.size() == 1);
  ASSERT_TRUE(result.Multi2[0].empty());
  ASSERT_TRUE(result.Multi3.size() == 2);
  ASSERT_TRUE(result.Multi3[0] == foobar);
  ASSERT_TRUE(result.Multi3[1] == barfoo);

  ASSERT_TRUE(unparsedArguments.size() == 1);
  ASSERT_TRUE(unparsedArguments[0] == "bar");
  ASSERT_TRUE(keywordsMissingValue == missing);

  return true;
}

bool testArgumentParserDynamic()
{
  Result result;
  std::vector<std::string> unparsedArguments;
  std::vector<std::string> keywordsMissingValue;

  cmArgumentParser<void>{}
    .Bind("OPTION_1"_s, result.Option1)
    .Bind("OPTION_2"_s, result.Option2)
    .Bind("STRING_1"_s, result.String1)
    .Bind("STRING_2"_s, result.String2)
    .Bind("LIST_1"_s, result.List1)
    .Bind("LIST_2"_s, result.List2)
    .Bind("LIST_3"_s, result.List3)
    .Bind("MULTI_1"_s, result.Multi1)
    .Bind("MULTI_2"_s, result.Multi2)
    .Bind("MULTI_3"_s, result.Multi3)
    .Parse(args, &unparsedArguments, &keywordsMissingValue);

  return verifyResult(result, unparsedArguments, keywordsMissingValue);
}

bool testArgumentParserStatic()
{
  static auto const parser = //
    cmArgumentParser<Result>{}
      .Bind("OPTION_1"_s, &Result::Option1)
      .Bind("OPTION_2"_s, &Result::Option2)
      .Bind("STRING_1"_s, &Result::String1)
      .Bind("STRING_2"_s, &Result::String2)
      .Bind("LIST_1"_s, &Result::List1)
      .Bind("LIST_2"_s, &Result::List2)
      .Bind("LIST_3"_s, &Result::List3)
      .Bind("MULTI_1"_s, &Result::Multi1)
      .Bind("MULTI_2"_s, &Result::Multi2)
      .Bind("MULTI_3"_s, &Result::Multi3);

  std::vector<std::string> unparsedArguments;
  std::vector<std::string> keywordsMissingValue;
  Result const result =
    parser.Parse(args, &unparsedArguments, &keywordsMissingValue);

  return verifyResult(result, unparsedArguments, keywordsMissingValue);
}

} // namespace

int testArgumentParser(int /*unused*/, char* /*unused*/ [])
{
  if (!testArgumentParserDynamic()) {
    std::cout << "While executing testArgumentParserDynamic().\n";
    return -1;
  }

  if (!testArgumentParserStatic()) {
    std::cout << "While executing testArgumentParserStatic().\n";
    return -1;
  }

  return 0;
}
