/* -*- 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 "identity.hpp"
#include "pib-impl.hpp"
#include "pib.hpp"

namespace ndn {
namespace security {

const name::Component Identity::EMPTY_KEY_ID;

Identity::Identity()
  : m_hasDefaultKey(false)
  , m_needRefreshKeys(false)
  , m_impl(nullptr)
{
}

Identity::Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
  : m_name(identityName)
  , m_hasDefaultKey(false)
  , m_needRefreshKeys(true)
  , m_impl(impl)
{
  validityCheck();

  if (needInit)
    m_impl->addIdentity(m_name);
  else if (!m_impl->hasIdentity(m_name))
    BOOST_THROW_EXCEPTION(Pib::Error("Identity: " + m_name.toUri() + " does not exist"));
}

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

  return m_name;
}

Key
Identity::addKey(const v1::PublicKey& publicKey, const name::Component& keyId)
{
  validityCheck();

  name::Component actualKeyId = keyId;
  if (actualKeyId == EMPTY_KEY_ID) {
    const Block& digest = publicKey.computeDigest();
    actualKeyId = name::Component(digest.wire(), digest.size());
  }

  if (!m_needRefreshKeys && m_keys.find(actualKeyId) == m_keys.end()) {
    // if we have already loaded all the keys, but the new key is not one of them
    // the KeyContainer should be refreshed
    m_needRefreshKeys = true;
  }

  return Key(m_name, actualKeyId, publicKey, m_impl);
}

void
Identity::removeKey(const name::Component& keyId)
{
  validityCheck();

  if (m_hasDefaultKey && m_defaultKey.getKeyId() == keyId)
    m_hasDefaultKey = false;

  m_impl->removeKey(m_name, keyId);
  m_needRefreshKeys = true;
}

Key
Identity::getKey(const name::Component& keyId) const
{
  validityCheck();

  return Key(m_name, keyId, m_impl);
}

const KeyContainer&
Identity::getKeys() const
{
  validityCheck();

  if (m_needRefreshKeys) {
    m_keys = KeyContainer(m_name, m_impl->getKeysOfIdentity(m_name), m_impl);
    m_needRefreshKeys = false;
  }

  return m_keys;
}

Key&
Identity::setDefaultKey(const name::Component& keyId)
{
  validityCheck();

  m_defaultKey = Key(m_name, keyId, m_impl);
  m_hasDefaultKey = true;

  m_impl->setDefaultKeyOfIdentity(m_name, keyId);
  return m_defaultKey;
}

Key&
Identity::setDefaultKey(const v1::PublicKey& publicKey, const name::Component& keyId)
{
  const Key& keyEntry = addKey(publicKey, keyId);
  return setDefaultKey(keyEntry.getKeyId());
}

Key&
Identity::getDefaultKey() const
{
  validityCheck();

  if (!m_hasDefaultKey) {
    m_defaultKey = Key(m_name, m_impl->getDefaultKeyOfIdentity(m_name), m_impl);
    m_hasDefaultKey = true;
  }

  return m_defaultKey;
}

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

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

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

} // namespace security
} // namespace ndn
