/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#include <getopt.h>
#include "core/logger.hpp"
#include "fw/forwarder.hpp"
#include "mgmt/internal-face.hpp"
#include "mgmt/fib-manager.hpp"
#include "mgmt/local-control-header-manager.hpp"
#include "face/tcp-channel-factory.hpp"

#ifdef HAVE_UNIX_SOCKETS
#include "face/unix-stream-channel-factory.hpp"
#endif

namespace nfd {

NFD_LOG_INIT("Main");

struct ProgramOptions
{
  struct TcpOutgoing
  {
    TcpOutgoing(std::pair<std::string, std::string> endpoint)
      : m_endpoint(endpoint)
    {
    }

    std::pair<std::string, std::string> m_endpoint;
    std::vector<Name> m_prefixes;
  };

  bool m_showUsage;
  std::pair<std::string, std::string> m_tcpListen;
  std::vector<TcpOutgoing> m_tcpOutgoings;
  std::string m_unixListen;
};

static ProgramOptions g_options;
static Forwarder* g_forwarder;
static FibManager* g_fibManager;
static LocalControlHeaderManager* g_localControlHeaderManager;
static TcpChannelFactory* g_tcpFactory;
static shared_ptr<TcpChannel> g_tcpChannel;
static shared_ptr<InternalFace> g_internalFace;

#ifdef HAVE_UNIX_SOCKETS
static UnixStreamChannelFactory* g_unixFactory;
static shared_ptr<UnixStreamChannel> g_unixChannel;
#endif


void
usage(char* programName)
{
  printf(
    "%s --help\n\tshow this help and exit\n"
    "%s [--tcp-listen \"0.0.0.0:6363\"] "
#ifdef HAVE_UNIX_SOCKETS
       "[--unix-listen \"/var/run/nfd.sock\"] "
#endif
       "[--tcp-connect \"192.0.2.1:6363\" "
            "[--prefix </example>]]\n"
      "\trun forwarding daemon\n"
      "\t--tcp-listen <ip:port>: listen on IP and port\n"
#ifdef HAVE_UNIX_SOCKETS
      "\t--unix-listen <unix-socket-path>: listen on Unix socket\n"
#endif
      "\t--tcp-connect <ip:port>: connect to IP and port (can occur multiple times)\n"
      "\t--prefix <NDN name>: add this face as nexthop to FIB entry "
        "(must appear after --tcp-connect, can occur multiple times)\n"
    "\n",
    programName, programName
  );
}

inline std::pair<std::string, std::string>
parseIpPortPair(const std::string& s)
{
  size_t pos = s.rfind(":");
  if (pos == std::string::npos) {
    throw std::invalid_argument("ip:port");
  }

  return std::make_pair(s.substr(0, pos), s.substr(pos+1));
}

bool
parseCommandLine(int argc, char** argv)
{
  g_options.m_showUsage = false;
  g_options.m_tcpListen = std::make_pair("0.0.0.0", "6363");
  g_options.m_unixListen = "/var/run/nfd.sock";
  g_options.m_tcpOutgoings.clear();

  while (1) {
    int option_index = 0;
    static ::option long_options[] = {
      { "help"          , no_argument      , 0, 0 },
      { "tcp-listen"    , required_argument, 0, 0 },
      { "tcp-connect"   , required_argument, 0, 0 },
      { "prefix"        , required_argument, 0, 0 },
      { "unix-listen"   , required_argument, 0, 0 },
      { 0               , 0                , 0, 0 }
    };
    int c = getopt_long_only(argc, argv, "", long_options, &option_index);
    if (c == -1) break;

    switch (c) {
      case 0:
        switch (option_index) {
          case 0://help
            g_options.m_showUsage = true;
            break;
          case 1://tcp-listen
            g_options.m_tcpListen = parseIpPortPair(::optarg);
            break;
          case 2://tcp-connect
            g_options.m_tcpOutgoings.push_back(parseIpPortPair(::optarg));
            break;
          case 3://prefix
            if (g_options.m_tcpOutgoings.empty()) {
              return false;
            }
            g_options.m_tcpOutgoings.back().m_prefixes.push_back(Name(::optarg));
            break;
          case 4://unix-listen
            g_options.m_unixListen = ::optarg;
            break;
        }
        break;
    }
  }
  return true;
}

void
onFaceFail(shared_ptr<Face> face, const std::string& reason)
{
  g_forwarder->removeFace(face);
}

void
onFaceEstablish(shared_ptr<Face> newFace, std::vector<Name>* prefixes)
{
  g_forwarder->addFace(newFace);
  newFace->onFail += bind(&onFaceFail, newFace, _1);

  // add nexthop on prefixes
  if (prefixes != 0) {
    Fib& fib = g_forwarder->getFib();
    for (std::vector<Name>::iterator it = prefixes->begin();
        it != prefixes->end(); ++it) {
      std::pair<shared_ptr<fib::Entry>, bool> fibInsertResult =
        fib.insert(*it);
      shared_ptr<fib::Entry> fibEntry = fibInsertResult.first;
      fibEntry->addNextHop(newFace, 0);
    }
  }
}

void
onFaceError(const std::string& reason)
{
  throw std::runtime_error(reason);
}

void
initializeTcp()
{
  g_tcpFactory = new TcpChannelFactory();
  g_tcpChannel = g_tcpFactory->create(g_options.m_tcpListen.first,
                                      g_options.m_tcpListen.second);
  g_tcpChannel->listen(
    bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
    &onFaceError);

  for (std::vector<ProgramOptions::TcpOutgoing>::iterator it =
      g_options.m_tcpOutgoings.begin();
      it != g_options.m_tcpOutgoings.end(); ++it) {
    g_tcpChannel->connect(it->m_endpoint.first, it->m_endpoint.second,
      bind(&onFaceEstablish, _1, &(it->m_prefixes)), &onFaceError);
  }
}

#ifdef HAVE_UNIX_SOCKETS
void
initializeUnix()
{
  g_unixFactory = new UnixStreamChannelFactory();
  g_unixChannel = g_unixFactory->create(g_options.m_unixListen);

  g_unixChannel->listen(
    bind(&onFaceEstablish, _1, static_cast<std::vector<Name>*>(0)),
    &onFaceError);
}
#endif

void
initializeMgmt()
{
  g_internalFace = make_shared<InternalFace>();
  g_forwarder->addFace(g_internalFace);

  g_fibManager = new FibManager(g_forwarder->getFib(),
                                bind(&Forwarder::getFace, g_forwarder, _1),
                                g_internalFace);

  g_localControlHeaderManager =
    new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
                                  g_internalFace);

  shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
  entry->addNextHop(g_internalFace, 0);
}

int
main(int argc, char** argv)
{
  bool isCommandLineValid = parseCommandLine(argc, argv);
  if (!isCommandLineValid) {
    usage(argv[0]);
    return 1;
  }
  if (g_options.m_showUsage) {
    usage(argv[0]);
    return 0;
  }

  g_forwarder = new Forwarder();
  initializeTcp();
#ifdef HAVE_UNIX_SOCKETS
  initializeUnix();
#endif
  initializeMgmt();

  /// \todo Add signal processing to gracefully terminate the app

  try {
    getGlobalIoService().run();
  } catch(std::exception& ex) {
    NFD_LOG_ERROR(ex.what());
    return 1;
  }

  return 0;
}

} // namespace nfd

int
main(int argc, char** argv)
{
  return nfd::main(argc, argv);
}
