/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2017, 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/>.
 */

#ifndef NDNS_DAEMON_NAME_SERVER_HPP
#define NDNS_DAEMON_NAME_SERVER_HPP

#include "zone.hpp"
#include "rrset.hpp"
#include "db-mgr.hpp"
#include "ndns-label.hpp"
#include "ndns-tlv.hpp"
#include "validator.hpp"
#include "common.hpp"

#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/face.hpp>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>

#include <sstream>
#include <stdexcept>

namespace ndn {
namespace ndns {

/**
 * @brief provides authoritative name server.
 *
 * The authoritative name server handles NDNS query and update.
 */
class NameServer : noncopyable
{
  DEFINE_ERROR(Error, std::runtime_error);

public:
  explicit
  NameServer(const Name& zoneName, const Name& certName, Face& face, DbMgr& dbMgr,
             KeyChain& keyChain, security::v2::Validator& validator);

NDNS_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  void
  onInterest(const Name& prefix, const Interest& interest);

  /**
   * @brief handle NDNS query message
   */
  void
  handleQuery(const Name& prefix, const Interest& interest, const label::MatchResult& re);

  /**
   * @brief handle NDNS update message
   */
  void
  handleUpdate(const Name& prefix, const Interest& interest, const label::MatchResult& re);

  void
  onRegisterFailed(const ndn::Name& prefix, const std::string& reason);

  void
  doUpdate(const shared_ptr<const Interest>& interest, const shared_ptr<const Data>& data);

public:
  const Name&
  getNdnsPrefix()
  {
    return m_ndnsPrefix;
  }

  const Zone&
  getZone() const
  {
    return m_zone;
  }

  const time::milliseconds&
  getContentFreshness() const
  {
    return m_contentFreshness;
  }

  /**
   * @brief set the Data fresh period
   */
  void
  setContentFreshness(const time::milliseconds& contentFreshness)
  {
    BOOST_ASSERT(contentFreshness > time::milliseconds::zero());
    m_contentFreshness = contentFreshness;
  }

private:
  Zone m_zone;
  DbMgr& m_dbMgr;

  Name m_ndnsPrefix;
  Name m_certName;

  time::milliseconds m_contentFreshness;

  Face& m_face;
  KeyChain& m_keyChain;
  security::v2::Validator& m_validator;
};

} // namespace ndns
} // namespace ndn

#endif // NDNS_DAEMON_NAME_SERVER_HPP
