/**
 * AUSF API
 * AUSF UE Authentication Service. © 2020, 3GPP Organizational Partners (ARIB,
 * ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
 *
 * The version of the OpenAPI document: 1.1.1
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator
 * (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
 * the class manually.
 */

#include "pistache/endpoint.h"
#include "pistache/http.h"
#include "pistache/router.h"
#ifdef __linux__
#include <signal.h>
#include <unistd.h>
#include <vector>
#endif

#include "AuthenticationResultDeletionApiImpl.h"
#include "DefaultApiImpl.h"

#include "logger.hpp"
#include "options.hpp"
#include "ausf_config.hpp"
#include "itti.hpp"
#include "ausf_app.hpp"



#define PISTACHE_SERVER_THREADS 2
#define PISTACHE_SERVER_MAX_REQUEST_SIZE 32768
#define PISTACHE_SERVER_MAX_RESPONSE_SIZE 32768

static Pistache::Http::Endpoint *httpEndpoint;
#ifdef __linux__
static void sigHandler [[noreturn]] (int sig) {
  switch (sig) {
  case SIGINT:
  case SIGQUIT:
  case SIGTERM:
  case SIGHUP:
  default:
    httpEndpoint->shutdown();
    break;
  }
  exit(0);
}

static void setUpUnixSignals(std::vector<int> quitSignals) {
  sigset_t blocking_mask;
  sigemptyset(&blocking_mask);
  for (auto sig : quitSignals)
    sigaddset(&blocking_mask, sig);

  struct sigaction sa;
  sa.sa_handler = sigHandler;
  sa.sa_mask = blocking_mask;
  sa.sa_flags = 0;

  for (auto sig : quitSignals)
    sigaction(sig, &sa, nullptr);
}
#endif
using namespace std;
using namespace ausf_application;

using namespace org::openapitools::server::api;

using namespace config;

ausf_config ausf_cfg;
itti_mw *itti_inst = nullptr;
ausf_app *ausf_app_inst = nullptr;

int main(int argc, char **argv) {
#ifdef __linux__
  std::vector<int> sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
  setUpUnixSignals(sigs);
#endif
  // Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(8080));
  srand(time(NULL));
  if  (!Options::parse(argc, argv)) {
    std::cout<<"Options::parse() failed\n Please input args"<<std::endl;
    return 1;
  }

  Logger::init( "ausf" , Options::getlogStdout() , Options::getlogRotFilelog());
  Logger::ausf_server().startup("Start AUSF");
  Logger::ausf_app().startup("Start ausf_app");
  Logger::ausf_app().info("Options parsed!");

  ausf_cfg.load(Options::getlibconfigConfig());
  ausf_cfg.display();

  Logger::ausf_app().info("Initiating ITTI server!");
  itti_inst = new itti_mw();
  util::thread_sched_params itti_timer_sched_params;
  itti_inst->start(itti_timer_sched_params);
  ausf_app_inst = new ausf_app();

  //Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(ausf_cfg.sbi.port));
  Pistache::Address addr(std::string(inet_ntoa (*((struct in_addr *)&ausf_cfg.sbi.addr4))), Pistache::Port(ausf_cfg.sbi.port));

  httpEndpoint = new Pistache::Http::Endpoint((addr));
  auto router = std::make_shared<Pistache::Rest::Router>();

  auto opts =
      Pistache::Http::Endpoint::options().threads(PISTACHE_SERVER_THREADS);
  opts.flags(Pistache::Tcp::Options::ReuseAddr);
  opts.maxRequestSize(PISTACHE_SERVER_MAX_REQUEST_SIZE);
  opts.maxResponseSize(PISTACHE_SERVER_MAX_RESPONSE_SIZE);
  httpEndpoint->init(opts);

  // Logger::init( "ausf" , true , true);
  // Logger::ausf_server().startup("Entering main...");



  AuthenticationResultDeletionApiImpl AuthenticationResultDeletionApiserver(
      router);
  AuthenticationResultDeletionApiserver.init();
  DefaultApiImpl DefaultApiserver(router);
  DefaultApiserver.init();

  httpEndpoint->setHandler(router->handler());
  httpEndpoint->serve();

  httpEndpoint->shutdown();
}
