/* -*- 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 "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 boost::asio::io_service g_ioService;
static ProgramOptions g_options;
static Forwarder* g_forwarder;
static FibManager* g_fibManager;
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_ioService);
  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_ioService);
  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);

  shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd/fib").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(g_ioService);
  initializeTcp();
#ifdef HAVE_UNIX_SOCKETS
  initializeUnix();
#endif
  initializeMgmt();

  /// \todo Add signal processing to gracefully terminate the app
  
  try {
    g_ioService.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);
}
