#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>

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={
  {"in1_out1", module_in1_out1},
  {"in2_out1", module_in2_out1},
  {"inVariable_out1", module_inVariable_out1}};

  registerOperatorsFromModules();

  // this test checks if operators with non variable input numbers can be
  // chained
  bandit::describe("Process creation for non variable operators", []() {
    // in1_out1: child oper 2
    // in2_out1: child in1_out1 and in1_out1:
    // in1_out1: infile: 1
    // in1_out1: infile 2
    // outfile: filled by in1_out1
    std::vector<const char *> test_argv{ "-in1_out1",  "-in2_out1",
                                         "-in1_out1",  "input_file1",
                                         "-in1_out1",  "input_file2",
                                         "output_file" };

    std::vector<unsigned int> expectedInputs{ 1, 2, 1, 1 };
    std::vector<unsigned int> expectedOutputs{ 1, 1, 1, 1 };

    /*clang-format off*/
    //          Name     Func  Help   oper    mod    in
    //                                           num    out
    /*clang-format on*/

    g_processManager.createProcessesFromInput(test_argv.size(), &test_argv[0]);

    int i;
    for (i = 0; i < g_processManager.processNums(); i++)
      {
        auto process = g_processManager.getProcess(i);
        bandit::it(
            "created inputs for:"
                + std::string(g_processManager.getProcess(i).operatorName),
            [&]() {
              AssertThat(process.inputStreams.size(),
                         snowhouse::Equals(expectedInputs[i]));
            });
        bandit::it(
            "created outputs for: "
                + std::string(g_processManager.getProcess(i).operatorName),
            [&]() {
              AssertThat(process.outputStreams.size(),
                         snowhouse::Equals(expectedOutputs[i]));
            });
      }
    bandit::it("created right amount of processes", [&]() {
      AssertThat(i, snowhouse::Equals(g_processManager.processNums()));
    });
  });

  g_processManager.clearProcesses();

  // this test checks if multiple operators can be chained if the first operator
  // is part of a module with variable number of input streams
  bandit::describe(
      "Process creation containing operators with variable number of input "
      "streams",
      []() {
        // in1_out1: child oper 2
        // in2_out1: child in1_out1 and in1_out1:
        // in1_out1: infile: 1
        // in1_out1: infile 2
        // outfile: filled by in1_out1
        std::vector<const char *> test_argv{
          "-inVariable_out1", "-in2_out1",   "-in1_out1", "input_file1",
          "-in1_out1",        "input_file2", "-in1_out1", "input_file3",
          "-in1_out1",        "input_file4", "out"
        };

        std::vector<unsigned int> expectedInputs{ 3, 2, 1, 1, 1, 1 };
        std::vector<unsigned int> expectedOutputs{ 1, 1, 1, 1, 1, 1 };

        g_processManager.createProcessesFromInput(test_argv.size(),
                                                  &test_argv[0]);

        int i;
        for (i = 0; i < g_processManager.processNums(); i++)
          {
            auto process = g_processManager.getProcess(i);
            std::string runInfo
                = std::string(g_processManager.getProcess(i).operatorName)
                  + " in run: " + std::to_string(i + 1);
            bandit::it("created inputs for:" + runInfo, [&]() {
              AssertThat(process.inputStreams.size(),
                         snowhouse::Equals(expectedInputs[i]));
            });
            bandit::it("created outputs for: " + runInfo, [&]() {
              AssertThat(process.outputStreams.size(),
                         snowhouse::Equals(expectedOutputs[i]));
            });
          }
        bandit::it("created right amount of processes", [&]() {
          AssertThat(i, snowhouse::Equals(g_processManager.processNums()));
        });
      });
});
int
main(int argc, char **argv)
{

  int result = bandit::run(argc, argv);

  return result;
}
