#include <PastisUtils.hpp>
#include <Kokkos_Core.hpp>

#include <RevisionInfo.hpp>
#include <rang.hpp>

#include <FPEManager.hpp>
#include <SignalManager.hpp>
#include <ConsoleManager.hpp>

#include <CLI/CLI.hpp>

std::string initialize(int& argc, char* argv[])
{
  long unsigned number = 10;
  std::string filename;

  std::cout << "Pastis version: "
            << rang::style::bold << RevisionInfo::version() << rang::style::reset << '\n';

  std::cout << "-------------------- "
            << rang::fg::green
            << "git info"
            << rang::fg::reset
            <<" -------------------------"
            << '\n';
  std::cout << "tag:  " << rang::fg::reset
            << rang::style::bold << RevisionInfo::gitTag() << rang::style::reset << '\n';
  std::cout << "HEAD: " << rang::style::bold << RevisionInfo::gitHead() << rang::style::reset << '\n';
  std::cout << "hash: " << rang::style::bold << RevisionInfo::gitHash() << rang::style::reset << "  (";

  if (RevisionInfo::gitIsClean()) {
    std::cout << rang::fgB::green << "clean" << rang::fg::reset;
  } else {
    std::cout << rang::fgB::red << "dirty" << rang::fg::reset;
  }
  std::cout << ")\n";
  std::cout << "-------------------------------------------------------\n";
  {
    CLI::App app{"Pastis help"};

    app.add_option("-n,--number", number, "Number of cells");//->required();

    app.add_option("filename,-f,--filename", filename, "gmsh file");//->required();

    int threads=-1;
    app.add_option("--threads", threads, "Number of Kokkos threads")->check(CLI::Range(1,std::numeric_limits<decltype(threads)>::max()));

    std::string colorize="auto";
    app.add_set("--colorize", colorize, {"auto", "yes", "no"}, "Colorize console output", true);

    bool disable_fpe = false;
    app.add_flag("--no-fpe", disable_fpe, "Do not trap floating point exceptions");
    bool disable_signals = false;
    app.add_flag("--no-signal", disable_signals, "Do not catches signals");

    std::string pause_on_error="auto";
    app.add_set("--pause-on-error", pause_on_error, {"auto", "yes", "no"}, "Pause for debugging on unexpected error", true);

    std::atexit([](){std::cout << rang::style::reset;});
    try {
      app.parse(argc, argv);
    } catch (const CLI::ParseError &e) {
      std::exit(app.exit(e));
    }

    ConsoleManager::init(colorize);
    FPEManager::init(not disable_fpe);
    SignalManager::setPauseForDebug(pause_on_error);
    SignalManager::init(not disable_signals);
  }

  Kokkos::initialize(argc,argv);
  std::cout << "-------------------- "
            << rang::fg::green
            << "exec info"
            << rang::fg::reset
            <<" ------------------------"
            << '\n';

  std::cout << rang::style::bold;
  Kokkos::DefaultExecutionSpace::print_configuration(std::cout);
  std::cout << rang::style::reset;
  std::cout << "-------------------------------------------------------\n";

  return filename;
}

void finalize()
{
  Kokkos::finalize();
}