/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016 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 "pib-impl.hpp"
#include "pib.hpp"
#include "../v2/certificate.hpp"

namespace ndn {
namespace security {

Key::Key()
  : m_hasDefaultCertificate(false)
  , m_needRefreshCerts(false)
  , m_impl(nullptr)
{
}

Key::Key(const Name& identityName, const name::Component& keyId,
         const v1::PublicKey& publicKey, shared_ptr<PibImpl> impl)
  : m_id(identityName)
  , m_keyId(keyId)
  , m_key(publicKey)
  , m_hasDefaultCertificate(false)
  , m_needRefreshCerts(true)
  , m_impl(impl)
{
  validityCheck();

  m_keyName = m_id;
  m_keyName.append(m_keyId);

  m_impl->addIdentity(m_id);
  m_impl->addKey(m_id, m_keyId, publicKey);
}

Key::Key(const Name& identityName, const name::Component& keyId,
         shared_ptr<PibImpl> impl)
  : m_id(identityName)
  , m_keyId(keyId)
  , m_hasDefaultCertificate(false)
  , m_needRefreshCerts(true)
  , m_impl(impl)
{
  validityCheck();

  m_keyName = m_id;
  m_keyName.append(m_keyId);

  m_key = m_impl->getKeyBits(m_id, m_keyId);
}

const Name&
Key::getName() const
{
  validityCheck();

  return m_keyName;
}

const Name&
Key::getIdentity() const
{
  validityCheck();

  return m_id;
}

const name::Component&
Key::getKeyId() const
{
  validityCheck();

  return m_keyId;
}

const v1::PublicKey&
Key::getPublicKey() const
{
  validityCheck();

  return m_key;
}

void
Key::addCertificate(const v1::IdentityCertificate& certificate)
{
  validityCheck();

  if (!m_needRefreshCerts &&
      m_certificates.find(certificate.getName()) == m_certificates.end()) {
    // if we have already loaded all the certificate, but the new certificate is not one of them
    // the CertificateContainer should be refreshed
    m_needRefreshCerts = true;
  }

  m_impl->addCertificate(certificate);
}

void
Key::removeCertificate(const Name& certName)
{
  validityCheck();

  if (m_hasDefaultCertificate && m_defaultCertificate.getName() == certName)
    m_hasDefaultCertificate = false;

  m_impl->removeCertificate(certName);
  m_needRefreshCerts = true;
}

v1::IdentityCertificate
Key::getCertificate(const Name& certName) const
{
  validityCheck();

  return m_impl->getCertificate(certName);
}

const CertificateContainer&
Key::getCertificates() const
{
  validityCheck();

  if (m_needRefreshCerts) {
    m_certificates = CertificateContainer(m_impl->getCertificatesOfKey(m_id, m_keyId), m_impl);
    m_needRefreshCerts = false;
  }

  return m_certificates;
}

const v1::IdentityCertificate&
Key::setDefaultCertificate(const Name& certName)
{
  validityCheck();

  m_defaultCertificate = m_impl->getCertificate(certName);
  m_impl->setDefaultCertificateOfKey(m_id, m_keyId, certName);
  m_hasDefaultCertificate = true;
  return m_defaultCertificate;
}

const v1::IdentityCertificate&
Key::setDefaultCertificate(const v1::IdentityCertificate& certificate)
{
  addCertificate(certificate);
  return setDefaultCertificate(certificate.getName());
}

const v1::IdentityCertificate&
Key::getDefaultCertificate() const
{
  validityCheck();

  if (!m_hasDefaultCertificate) {
    m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_id, m_keyId);
    m_hasDefaultCertificate = true;
  }

  return m_defaultCertificate;
}

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

bool
Key::operator!() const
{
  return (m_impl == nullptr);
}

void
Key::validityCheck() const
{
  if (m_impl == nullptr)
    BOOST_THROW_EXCEPTION(std::domain_error("Invalid Key instance"));
}

namespace v2 {

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

} // namespace v2

} // namespace security
} // namespace ndn
