/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014, Regents of the University of California.
 *
 * This file is part of NDNS (Named Data Networking Domain Name Service).
 * See AUTHORS.md for complete list of NDNS authors and contributors.
 *
 * NDNS is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "daemon/name-server.hpp"
#include "logger.hpp"
#include "config.hpp"
#include "daemon/config-file.hpp"
#include "ndn-cxx/security/key-chain.hpp"
#include <boost/program_options.hpp>

namespace ndn {
namespace ndns {

NDNS_LOG_INIT("NdnsDaemon");

/**
 * @brief Name Server Daemon
 * @note NdnsDaemon allows multiple name servers hosted by the same daemon, and they
 * share same KeyChain, DbMgr, Validator and Face
 */
class NdnsDaemon : noncopyable
{
public:
  DEFINE_ERROR(Error, std::runtime_error);

  explicit
  NdnsDaemon(const std::string& configFile, Face& face, Face& validatorFace)
    : m_face(face)
    , m_validatorFace(validatorFace)
  {
    try {
      ConfigFile config;
      NDNS_LOG_INFO("NnsnDaemon ConfigFile = " << configFile);

      config.addSectionHandler("zones",
                               bind(&NdnsDaemon::processZonesSection, this, _1, _3));
      config.addSectionHandler("hints",
                               bind(&NdnsDaemon::processHintsSection, this, _1, _3));

      config.parse(configFile, false);

    }
    catch (boost::filesystem::filesystem_error& e) {
      if (e.code() == boost::system::errc::permission_denied) {
        NDNS_LOG_FATAL("Permissions denied for " << e.path1());
      }
      else {
        NDNS_LOG_FATAL(e.what());
      }
    }
    catch (const std::exception& e) {
      NDNS_LOG_FATAL(e.what());
    }
  }

  void
  processHintsSection(const ndn::ndns::ConfigSection& section, const std::string& filename)
  {
    // hint is not supported yet
    ;
  }

  void
  processZonesSection(const ndn::ndns::ConfigSection& section, const std::string& filename)
  {
    using namespace boost::filesystem;
    using namespace ndn::ndns;
    using ndn::ndns::ConfigSection;

    if (section.begin() == section.end()) {
      throw Error("zones section is empty");
    }

    std::string dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db";
    ConfigSection::const_assoc_iterator item = section.find("dbFile");
    if (item != section.not_found()) {
      dbFile = item->second.get_value<std::string>();
    }
    NDNS_LOG_INFO("DbFile = " << dbFile);
    m_dbMgr = unique_ptr<DbMgr>(new DbMgr(dbFile));

    std::string validatorConfigFile = DEFAULT_CONFIG_PATH "/" "validator.conf";
    item = section.find("validatorConfigFile");
    if (item != section.not_found()) {
      validatorConfigFile = item->second.get_value<std::string>();
    }
    NDNS_LOG_INFO("ValidatorConfigFile = " << validatorConfigFile);
    m_validator = unique_ptr<Validator>(new Validator(m_validatorFace, validatorConfigFile));

    for (const auto& option : section) {
      Name name;
      Name cert;
      if (option.first == "zone") {
        try {
          name = option.second.get<Name>("name"); // exception leads to exit
        }
        catch (const std::exception& e) {
          NDNS_LOG_ERROR("Required `name' attribute missing in `zone' section");
          throw Error("Required `name' attribute missing in `zone' section");
        }
        try {
          cert = option.second.get<Name>("cert");
        }
        catch (std::exception&) {
          ;
        }


        if (!m_keyChain.doesIdentityExist(name)) {
          NDNS_LOG_FATAL("Identity: " << name << " does not exist in the KeyChain");
          throw Error("Identity does not exist in the KeyChain");
        }

        if (cert.empty()) {
          try {
            cert = m_keyChain.getDefaultCertificateNameForIdentity(name);
          }
          catch (std::exception& e) {
            NDNS_LOG_FATAL("Identity: " << name << " does not have default certificate. "
                           << e.what());
            throw Error("identity does not have default certificate");
          }
        }
        else {
          if (!m_keyChain.doesCertificateExist(cert)) {
            throw Error("Certificate `" + cert.toUri() + "` does not exist in the KeyChain");
          }
        }
        NDNS_LOG_TRACE("name = " << name << " cert = " << cert);
        m_servers.push_back(make_shared<NameServer>(name, cert, m_face, *m_dbMgr,
                                                    m_keyChain, *m_validator));
      }
    } // for
  }

private:
  Face& m_face;
  Face& m_validatorFace;
  unique_ptr<Validator> m_validator;
  unique_ptr<DbMgr> m_dbMgr;
  std::vector<shared_ptr<NameServer>> m_servers;
  KeyChain m_keyChain;
};

} // namespace ndns
} // namespace ndn

int
main(int argc, char* argv[])
{
  using std::string;
  using ndn::ndns::ConfigFile;
  using namespace ndn::ndns;

  ndn::ndns::log::init();
  string configFile = DEFAULT_CONFIG_PATH "/" "ndns.conf";

  try {
    namespace po = boost::program_options;
    po::variables_map vm;

    po::options_description generic("Generic Options");
    generic.add_options()("help,h", "print help message");

    po::options_description config("Configuration");
    config.add_options()
      ("config,c", po::value<string>(&configFile), "set the path of configuration file")
      ;

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(config);

    po::parsed_options parsed =
      po::command_line_parser(argc, argv).options(cmdline_options).run();

    po::store(parsed, vm);
    po::notify(vm);

    if (vm.count("help")) {
      std::cout << "Usage:\n"
                << "  ndns-daemon [-c configFile]\n"
                << std::endl;
      std::cout << generic << config << std::endl;
      return 0;
    }
  }
  catch (const std::exception& ex) {
    std::cerr << "Parameter Error: " << ex.what() << std::endl;

    return 1;
  }
  catch (...) {
    std::cerr << "Parameter Unknown error" << std::endl;
    return 1;
  }

  boost::asio::io_service io;
  ndn::Face face(io);
  ndn::Face validatorFace(io);

  try {
    // NFD does not to forward Interests to the face it was received from.
    // If the name server and its validator share same face,
    // the validator cannot be forwarded to the name server itself
    // For current, two faces are used here.

    // refs: http://redmine.named-data.net/issues/2206
    // @TODO enhance validator to get the certificate from the local db if it has

    NdnsDaemon daemon(configFile, face, validatorFace);
    face.processEvents();
  }
  catch (std::exception& e) {
    NDNS_LOG_FATAL("ERROR: " << e.what());
    return 1;
  }

  return 0;
}
