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

#include "../../src/modules.h"
#include "../../src/process_int.h"
#include "../../src/cdo_options.h"
#include "test_module_list.h"
#include <iostream>
/* clang-format off */

using namespace snowhouse;
ProcessManager g_processManager;
void
cdoExit()
{
  g_processManager.kill_processes();
  exit(EXIT_FAILURE);
}

go_bandit([]() {
//==============================================================================
    cdo::progname = "cdo_bandit_test";
    cdo::set_exit_function(cdoExit);
    cdo::set_context_function(process_inq_prompt);

  /* clang-format on */

  ParseStatus parseStatus;
  ProcessStatus processStatus;

  int result_parse;
  int expected_parse;
  int result_process;
  int expected_process;

  bandit::before_each([&]() {
  g_processManager.clear_processes(); });

  //-----------------------------Test_01------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for unprocessed inputs", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_unprocessedInput{
        "-in2_out1", "-in0_out1", "-in0_out1", "-in0_out1", "out" };
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_unprocessedInput.size(), &argv_unprocessedInput[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::UnprocessedInput);

  bandit::it("has detected unprocessed Input", [&]() {
    AssertThat(result_parse, snowhouse::Equals(expected_parse));
  });
  });

  //-----------------------------Test_02------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for miss placement of brackets", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_missingCloseBracket{
        "-in2_out1", "[", "-in0_out1", "-in0_out1", "out"
        };
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_missingCloseBracket.size(), &argv_missingCloseBracket[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::ClosingBracketMissing);
  bandit::it("it detected a missing ']'", [&]() {
    AssertThat(result_parse, snowhouse::Equals(expected_parse));
  });
  });

  //-----------------------------Test_03------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for miss placement of brackets", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_missingOpenBracket{
        "-in2_out1", "-in0_out1", "-in0_out1", "]", "out"
        };
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_missingOpenBracket.size(), &argv_missingOpenBracket[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::OpenBracketMissing);
  bandit::it("it detected a mising '[' ", [&]() {
    AssertThat(result_parse, snowhouse::Equals(expected_parse));
  });
  });

  //-----------------------------Test_04------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for miss placement of brackets", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_wrongBracketTooMany{
        "-in2_out1", "[", "-in0_out1", "-in0_out1", "-in0_out1", "]", "out"
    };
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_wrongBracketTooMany.size(), &argv_wrongBracketTooMany[0]);
  g_processManager.get_process_from_id(0)->check_stream_cnt();
  processStatus = g_processManager.get_process_from_id(0)->m_status;

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::Ok);
  result_process = static_cast<int>(processStatus);
  expected_process = static_cast<int>(ProcessStatus::TooManyStreams);

  bandit::it("detected too many inputs", [&]() {
    AssertThat(result_parse, Is().EqualTo(expected_parse));
    AssertThat(result_process, Is().EqualTo(expected_process));
  });
  });

  //-----------------------------Test_05------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for miss placement of brackets", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_wrongBracketTooFew{ 
        "-in2_out1", "[", "-in0_out1", "]", "out"
    };
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_wrongBracketTooFew.size(), &argv_wrongBracketTooFew[0]);
  g_processManager.get_process_from_id(0)->check_stream_cnt();
  processStatus = g_processManager.get_process_from_id(0)->m_status;

  bandit::it("detected too few inputs", [&]() {
    AssertThat(static_cast<int>(parseStatus),
               Is().EqualTo(static_cast<int>(ParseStatus::Ok)));
    AssertThat(static_cast<int>(processStatus),
               Is().EqualTo(static_cast<int>(ProcessStatus::TooFewStreams)));
  });
  });

  //-----------------------------Test_06------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for unprocessed inputs", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_missingOutFileOperHasDash{
        "-in2_out1"};
  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_missingOutFileOperHasDash.size(),
      &argv_missingOutFileOperHasDash[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::MissingOutFile);

  bandit::it("detected unprocessed Input", [&]() {
    AssertThat(result_parse, snowhouse::Equals(expected_parse));
  });
  });
  bandit::describe("Testing if cdo wildcards with additional unnecessary [] works", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_unnecessaty_brackets{ 
        "-in2_out1", "[", "[", "-in0_out1", "-in0_out1", "]", "]", "out"
    };

  /* clang-format on */
  parseStatus = g_processManager.create_processes_from_input(
      argv_unnecessaty_brackets.size(), &argv_unnecessaty_brackets[0]);
  g_processManager.get_process_from_id(0)->check_stream_cnt();
  processStatus = g_processManager.get_process_from_id(0)->m_status;

  bandit::it("should work", [&]() {
    AssertThat(static_cast<int>(parseStatus),
               Is().EqualTo(static_cast<int>(ParseStatus::Ok)));
    AssertThat(static_cast<int>(processStatus),
               Is().EqualTo(static_cast<int>(ProcessStatus::Ok)));
  });
  });
});

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

  return result;
}
