/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (c) 2013-2014,  Regents of the University of California.
 * All rights reserved.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * This file licensed under New BSD License.  See COPYING for detailed information about
 * ndn-cxx library copyright, permissions, and redistribution restrictions.
 *
 * @author Jeff Thompson <jefft0@remap.ucla.edu>
 */

#include "common.hpp"

#include "sec-public-info-memory.hpp"
#include "identity-certificate.hpp"

using namespace std;

namespace ndn {

SecPublicInfoMemory::~SecPublicInfoMemory()
{
}

bool
SecPublicInfoMemory::doesIdentityExist(const Name& identityName)
{
  string identityUri = identityName.toUri();
  return find(m_identityStore.begin(), m_identityStore.end(), identityUri) != m_identityStore.end();
}

void
SecPublicInfoMemory::addIdentity(const Name& identityName)
{
  string identityUri = identityName.toUri();
  if (find(m_identityStore.begin(), m_identityStore.end(), identityUri) != m_identityStore.end())
    return;

  m_identityStore.push_back(identityUri);
}

bool
SecPublicInfoMemory::revokeIdentity()
{
  throw Error("SecPublicInfoMemory::revokeIdentity not implemented");
}

bool
SecPublicInfoMemory::doesPublicKeyExist(const Name& keyName)
{
  return m_keyStore.find(keyName.toUri()) != m_keyStore.end();
}

void
SecPublicInfoMemory::addPublicKey(const Name& keyName, KeyType keyType, const PublicKey& publicKey)
{
  Name identityName = keyName.getPrefix(-1);

  addIdentity(identityName);

  m_keyStore[keyName.toUri()] = make_shared<KeyRecord>(keyType, publicKey);
}

shared_ptr<PublicKey>
SecPublicInfoMemory::getPublicKey(const Name& keyName)
{
  KeyStore::iterator record = m_keyStore.find(keyName.toUri());
  if (record == m_keyStore.end())
    throw Error("SecPublicInfoMemory::getPublicKey  " + keyName.toUri());

  return make_shared<PublicKey>(record->second->getKey());
}

bool
SecPublicInfoMemory::doesCertificateExist(const Name& certificateName)
{
  return m_certificateStore.find(certificateName.toUri()) != m_certificateStore.end();
}

void
SecPublicInfoMemory::addCertificate(const IdentityCertificate& certificate)
{
  const Name& certificateName = certificate.getName();
  const Name& keyName = certificate.getPublicKeyName();
  const Name& identity = keyName.getPrefix(-1);

  addIdentity(identity);
  addPublicKey(keyName, KEY_TYPE_RSA, certificate.getPublicKeyInfo());
  m_certificateStore[certificateName.toUri()] = make_shared<IdentityCertificate>(certificate);
}

shared_ptr<IdentityCertificate>
SecPublicInfoMemory::getCertificate(const Name& certificateName)
{
  CertificateStore::iterator record = m_certificateStore.find(certificateName.toUri());
  if (record == m_certificateStore.end())
    throw Error("SecPublicInfoMemory::getCertificate  " + certificateName.toUri());

  return record->second;
}

Name
SecPublicInfoMemory::getDefaultIdentity()
{
  return Name(m_defaultIdentity);
}

void
SecPublicInfoMemory::setDefaultIdentityInternal(const Name& identityName)
{
  string identityUri = identityName.toUri();
  if (find(m_identityStore.begin(), m_identityStore.end(), identityUri) != m_identityStore.end())
    m_defaultIdentity = identityUri;
  else
    // The identity doesn't exist, so clear the default.
    m_defaultIdentity.clear();
}

Name
SecPublicInfoMemory::getDefaultKeyNameForIdentity(const Name& identityName)
{
  return m_defaultKeyName;
}

void
SecPublicInfoMemory::setDefaultKeyNameForIdentityInternal(const Name& keyName)
{
  m_defaultKeyName = keyName;
}

Name
SecPublicInfoMemory::getDefaultCertificateNameForKey(const Name& keyName)
{
  return m_defaultCert;
}

void
SecPublicInfoMemory::setDefaultCertificateNameForKeyInternal(const Name& certificateName)
{
  m_defaultCert = certificateName;
}

void
SecPublicInfoMemory::getAllIdentities(std::vector<Name>& nameList, bool isDefault)
{
  throw Error("SecPublicInfoMemory::getAllIdentities not implemented");
}

void
SecPublicInfoMemory::getAllKeyNames(std::vector<Name>& nameList, bool isDefault)
{
  throw Error("SecPublicInfoMemory::getAllKeyNames not implemented");
}

void
SecPublicInfoMemory::getAllKeyNamesOfIdentity(const Name& identity,
                                              std::vector<Name>& nameList,
                                              bool isDefault)
{
  throw Error("SecPublicInfoMemory::getAllKeyNamesOfIdentity not implemented");
}

void
SecPublicInfoMemory::getAllCertificateNames(std::vector<Name>& nameList, bool isDefault)
{
  throw Error("SecPublicInfoMemory::getAllCertificateNames not implemented");
}

void
SecPublicInfoMemory::getAllCertificateNamesOfKey(const Name& keyName,
                                                 std::vector<Name>& nameList,
                                                 bool isDefault)
{
  throw Error("SecPublicInfoMemory::getAllCertificateNamesOfKey not implemented");
}

void
SecPublicInfoMemory::deleteCertificateInfo(const Name& certName)
{
  throw Error("SecPublicInfoMemory::deleteCertificateInfo not implemented");
}

void
SecPublicInfoMemory::deletePublicKeyInfo(const Name& keyName)
{
  throw Error("SecPublicInfoMemory::deletePublicKeyInfo not implemented");
}

void
SecPublicInfoMemory::deleteIdentityInfo(const Name& identityName)
{
  throw Error("SecPublicInfoMemory::deleteIdentityInfo not implemented");
}

} // namespace ndn
