/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014  Regents of the University of California,
 *                     Arizona Board of Regents,
 *                     Colorado State University,
 *                     University Pierre & Marie Curie, Sorbonne University,
 *                     Washington University in St. Louis,
 *                     Beijing Institute of Technology
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#ifndef NFD_DAEMON_MGMT_MANAGER_BASE_HPP
#define NFD_DAEMON_MGMT_MANAGER_BASE_HPP

#include "common.hpp"

#include "mgmt/command-validator.hpp"
#include "mgmt/internal-face.hpp"

#include <ndn-cxx/management/nfd-control-command.hpp>
#include <ndn-cxx/management/nfd-control-response.hpp>
#include <ndn-cxx/management/nfd-control-parameters.hpp>

namespace nfd {

using ndn::nfd::ControlCommand;
using ndn::nfd::ControlResponse;
using ndn::nfd::ControlParameters;

class InternalFace;

class ManagerBase
{
public:

  struct Error : public std::runtime_error
  {
    Error(const std::string& what) : std::runtime_error(what) {}
  };

  ManagerBase(shared_ptr<InternalFace> face, const std::string& privilege);

  virtual
  ~ManagerBase();

  void
  onCommandValidationFailed(const shared_ptr<const Interest>& command,
                            const std::string& error);

protected:

  static bool
  extractParameters(const Name::Component& parameterComponent,
                    ControlParameters& extractedParameters);

  void
  setResponse(ControlResponse& response,
              uint32_t code,
              const std::string& text);
  void
  setResponse(ControlResponse& response,
              uint32_t code,
              const std::string& text,
              const Block& body);

  void
  sendResponse(const Name& name,
               const ControlResponse& response);

  void
  sendResponse(const Name& name,
               uint32_t code,
               const std::string& text);

  void
  sendResponse(const Name& name,
               uint32_t code,
               const std::string& text,
               const Block& body);

  virtual bool
  validateParameters(const ControlCommand& command,
                     ControlParameters& parameters);

PUBLIC_WITH_TESTS_ELSE_PROTECTED:
  void
  addInterestRule(const std::string& regex,
                  const ndn::IdentityCertificate& certificate);

  void
  addInterestRule(const std::string& regex,
                  const Name& keyName,
                  const ndn::PublicKey& publicKey);

  void
  validate(const Interest& interest,
           const ndn::OnInterestValidated& onValidated,
           const ndn::OnInterestValidationFailed& onValidationFailed);

protected:
  shared_ptr<InternalFace> m_face;
};

inline void
ManagerBase::setResponse(ControlResponse& response,
                         uint32_t code,
                         const std::string& text)
{
  response.setCode(code);
  response.setText(text);
}

inline void
ManagerBase::setResponse(ControlResponse& response,
                         uint32_t code,
                         const std::string& text,
                         const Block& body)
{
  setResponse(response, code, text);
  response.setBody(body);
}

inline void
ManagerBase::addInterestRule(const std::string& regex,
                             const ndn::IdentityCertificate& certificate)
{
  m_face->getValidator().addInterestRule(regex, certificate);
}

inline void
ManagerBase::addInterestRule(const std::string& regex,
                             const Name& keyName,
                             const ndn::PublicKey& publicKey)
{
  m_face->getValidator().addInterestRule(regex, keyName, publicKey);
}

inline void
ManagerBase::validate(const Interest& interest,
                      const ndn::OnInterestValidated& onValidated,
                      const ndn::OnInterestValidationFailed& onValidationFailed)
{
  m_face->getValidator().validate(interest, onValidated, onValidationFailed);
}


} // namespace nfd

#endif // NFD_DAEMON_MGMT_MANAGER_BASE_HPP
