//
// Created by rhetenor on 13.09.18.
//
#include <boost/program_options.hpp>

#include <iostream>
#include <fstream>
#include <memory>
#include <signal.h>

#include "DriverFactory.h"
#include "input/InputDriver.h"

#include "PrintHandler.h"

using namespace flippR_driver;
namespace po = boost::program_options;

PrintHandler* print_handler = nullptr;

void __sigint_handler(int param)
{
  printf("Caught SIGINT... aborting!\n");
  exit(EXIT_SUCCESS);
}

static void show_usage(const std::string &name)
{
  std::cout << "Usage: " << name << " [-ipc=<input_pin_config_file> -imc=<input_matrix_config_file>] "
            << "[-opc=<output_pin_config_file> -odc=<output_display_config_file> -olc=<output_lamp_config_file>] "
            << "-osolc=<output_solenoid_config_file> -osc=<output_sound_config_file>]";

}
static void register_program_options(po::options_description &po_desc, boost::optional<std::string> &input_pin_config_file, std::string &input_matrix_config_file,
        boost::optional<std::string> &output_pin_config_file,  std::string &output_display_config_file, std::string &output_lamp_config_file, std::string &output_solenoid_config_file, std::string &output_sound_config_file)
{
  po_desc.add_options()
  ("help", "print_help_message")
  ("input_pin_config,ipc", po::value<boost::optional<std::string>>(&input_pin_config_file), "input pin config file")
  ("input_matrix_config,imc", po::value<std::string>(&input_matrix_config_file), "input matrix config file")
  ("output_pin_config,opc", po::value<boost::optional<std::string>>(&output_pin_config_file), "output pin config file")
  ("output_display_config,idc", po::value<std::string>(&output_display_config_file), "output display config file")
  ("output_lamp_config,ilc", po::value<std::string>(&output_lamp_config_file), "output lamp config file")
  ("output_solenoid_config,isolc", po::value<std::string>(&output_solenoid_config_file), "output solenoid config file")
  ("output_sound_config,isc", po::value<std::string>(&output_sound_config_file), "output sound config file")
  ;
}

static PrintHandler* start_print_handler(const std::string &input_config_file, const std::string &matrix_config_file)
{
  std::ifstream input_config;
  std::ifstream matrix_config;
  try
  {
    input_config.open(input_config_file);
    matrix_config.open(matrix_config_file);
  }
  catch(const std::exception& e)
  {
    std::cout << e.what();
    exit(EXIT_FAILURE);
  }

  std::shared_ptr<input::InputDriver> driver = flippR_driver::get_InputDriver(input_config, matrix_config);

  return new PrintHandler(driver);
}

int main (int argc, char *argv[])
{
  if(argc < 3)
  {
    show_usage(argv[0]);
    exit(EXIT_FAILURE);
  }

  // registering sigint
  signal(SIGINT, __sigint_handler);

  po::options_description po_desc("Options");
  boost::optional<std::string> input_pin_config_file, output_pin_config_file;

  std::string input_matrix_config_file, output_display_config_file, output_lamp_config_file, output_solenoid_config_file, output_sound_config_file;

  register_program_options(po_desc, input_pin_config_file, input_matrix_config_file, output_pin_config_file, output_display_config_file, output_lamp_config_file, output_solenoid_config_file, output_sound_config_file);

  // todo parse

  if(input_pin_config_file)
  {
    print_handler = start_print_handler(*input_pin_config_file, input_matrix_config_file);
  }

  if(output_pin_config_file)
  {
    start_output_driver(*output_pin_config_file, )
  }
  while(1);

  return 0;
}
