#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.killProcesses();
  exit(EXIT_FAILURE);
}

go_bandit([]() {
//==============================================================================
    cdo::progname = "cdo_bandit_test";
    cdo::setExitFunction(cdoExit);
    cdo::setContextFunction(processInqPrompt);
    modules={
        {"in0_out1", module_in0_out1},
        {"in1_out1", module_in1_out1},
        {"in2_out1", module_in2_out1},
        {"inVariable_out0", module_inVariable_out0}};
    registerOperatorsFromModules();

  /* clang-format on */

  ParseStatus parseStatus;
  ProcessStatus processStatus;

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

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

  //-----------------------------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.createProcessesFromInput(
      argv_unprocessedInput.size(), &argv_unprocessedInput[0]);

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

  bandit::it("has 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.createProcessesFromInput(
      argv_missingCloseBracket.size(), &argv_missingCloseBracket[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::ClosingBracketMissing);
  bandit::it("it misses a ']'", [&]() {
    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.createProcessesFromInput(
      argv_missingOpenBracket.size(), &argv_missingOpenBracket[0]);

  result_parse = static_cast<int>(parseStatus);
  expected_parse = static_cast<int>(ParseStatus::OpenBracketMissing);
  bandit::it("it misses a '['", [&]() {
    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.createProcessesFromInput(
      argv_wrongBracketTooMany.size(), &argv_wrongBracketTooMany[0]);
  g_processManager.getProcess(0).checkStreamCnt();
  processStatus = g_processManager.getProcess(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("this one has 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.createProcessesFromInput(
      argv_wrongBracketTooFew.size(), &argv_wrongBracketTooFew[0]);
  g_processManager.getProcess(0).checkStreamCnt();
  processStatus = g_processManager.getProcess(0).m_status;

  bandit::it("this one has 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.createProcessesFromInput(
      argv_missingOutFileOperHasDash.size(),
      &argv_missingOutFileOperHasDash[0]);

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

  bandit::it("has unprocessed Input", [&]() {
    AssertThat(result_parse, snowhouse::Equals(expected_parse));
  });
  });
  //-----------------------------Test_06------------------------------------------
  //------------------------------------------------------------------------------
  bandit::describe("Negative test for unprocessed inputs", [&]() {
  /* clang-format off */
    std::vector<const char *> argv_missingOutFileOperHasntDash{
        "in2_out1"};
  /* clang-format on */
  parseStatus = g_processManager.createProcessesFromInput(
      argv_missingOutFileOperHasntDash.size(),
      &argv_missingOutFileOperHasntDash[0]);

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

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

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

  return result;
}
