#ifndef PROCESS_MANAGER_H
#define PROCESS_MANAGER_H

// Stdlib includes
#include <map>
#include <set>
#include <string>
#include <vector>
#include <string>
#include <memory>

#include <pthread.h>

// cdo includes

// Froward declarations
class Process;

// Error codes
enum class ParseStatus
{
  Ok = 0,
  OpenBracketMissing = -1,
  ClosingBracketMissing = -2,
  UnprocessedInput = -3,
  MissingOutFile = -4,
  MissingObase = -5,
  OperatorNotFirst = -6,
  FileIsInAndOutput = -7

};
class ProcessManager
{

private:
  std::map<int, std::shared_ptr<Process>> m_processes;
  std::vector<pthread_t> m_threadIDs;

  int m_numProcesses = 0;
  int m_numProcessesActive = 0;

  std::set<std::string> handle_first_operator(int p_argcStart, int argc,const std::vector<std::string> &argv, const std::shared_ptr<Process> &p_rootProcess);
  void check_single_bracket_only(const char *p_argvEntry, char p_bracketType);
  void handle_parse_error(ParseStatus p_parseStatus);
  int get_num_variable_input_operators();
  std::vector<std::string> get_operator_argv(std::string operatorArguments);

  const std::shared_ptr<Process> create_process_from_command(const std::string &p_command);
  const std::shared_ptr<Process> create_child_process_for(const std::shared_ptr<Process> &p_parentProcess,  const std::string &p_command);

public:
  ParseStatus create_processes_from_input(int argc, const std::vector<std::string> &argv);
  void create_processes(int argc, const std::vector<std::string> &argv);
  void run_processes();
  void kill_processes();
  void validate_processes();
  void clear_processes();
  int get_num_processes();
  int get_num_active_processes();
  const std::shared_ptr<Process> &get_process_from_id(int p_processID);
};

#endif
