/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "key.hpp"
#include "detail/key-impl.hpp"
#include "../v2/certificate.hpp"

namespace ndn {
namespace security {
namespace pib {

Key::Key() = default;

Key::Key(weak_ptr<detail::KeyImpl> impl)
  : m_impl(impl)
{
}

const Name&
Key::getName() const
{
  return lock()->getName();
}

const Name&
Key::getIdentity() const
{
  return lock()->getIdentity();
}

KeyType
Key::getKeyType() const
{
  return lock()->getKeyType();
}

const Buffer&
Key::getPublicKey() const
{
  return lock()->getPublicKey();
}

void
Key::addCertificate(const v2::Certificate& certificate)
{
  return lock()->addCertificate(certificate);
}

void
Key::removeCertificate(const Name& certName)
{
  return lock()->removeCertificate(certName);
}

v2::Certificate
Key::getCertificate(const Name& certName) const
{
  return lock()->getCertificate(certName);
}

const CertificateContainer&
Key::getCertificates() const
{
  return lock()->getCertificates();
}

const v2::Certificate&
Key::setDefaultCertificate(const Name& certName)
{
  return lock()->setDefaultCertificate(certName);
}

const v2::Certificate&
Key::setDefaultCertificate(const v2::Certificate& certificate)
{
  return lock()->setDefaultCertificate(certificate);
}

const v2::Certificate&
Key::getDefaultCertificate() const
{
  return lock()->getDefaultCertificate();
}

Key::operator bool() const
{
  return !(this->operator!());
}

bool
Key::operator!() const
{
  return m_impl.expired();
}

shared_ptr<detail::KeyImpl>
Key::lock() const
{
  auto impl = m_impl.lock();

  if (impl == nullptr) {
    BOOST_THROW_EXCEPTION(std::domain_error("Invalid key instance"));
  }

  return impl;
}

} // namespace pib

namespace v2 {

Name
constructKeyName(const Name& identity, const name::Component& keyId)
{
  Name keyName = identity;
  keyName
    .append(Certificate::KEY_COMPONENT)
    .append(keyId);
  return keyName;
}

bool
isValidKeyName(const Name& keyName)
{
  return (keyName.size() > Certificate::MIN_KEY_NAME_LENGTH &&
          keyName.get(-Certificate::MIN_KEY_NAME_LENGTH) == Certificate::KEY_COMPONENT);
}

Name
extractIdentityFromKeyName(const Name& keyName)
{
  if (!isValidKeyName(keyName)) {
    BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` "
                                                "does not follow the naming conventions"));
  }

  return keyName.getPrefix(-Certificate::MIN_KEY_NAME_LENGTH); // trim everything after and including "KEY"
}

} // namespace v2

} // namespace security
} // namespace ndn
