/* -*- 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.
 */

#ifndef NDN_SECURITY_PIB_IDENTITY_HPP
#define NDN_SECURITY_PIB_IDENTITY_HPP

#include "key-container.hpp"

namespace ndn {
namespace security {

class PibImpl;
class Pib;
class IdentityContainer;

/**
 * @brief represents an identity
 *
 * Identity is at the top level in PIB's Identity-Key-Certificate hierarchy.
 * An identity has a Name, and contains one or more keys, one of which is set
 * as the default key of this identity.  Properties of a key can be accessed
 * after obtaining a Key object.
 *
 * @throw PibImpl::Error when underlying implementation has non-semantic error.
 */
class Identity
{
public:
  friend class Pib;
  friend class IdentityContainer;
  friend class KeyChain;

public:
  /**
   * @brief Default Constructor
   *
   * Identity created using this default constructor is just a place holder.
   * It must obtain an actual instance from Pib::getIdentity(...).  A typical
   * usage would be for exception handling:
   *
   *   Identity id;
   *   try {
   *     id = pib.getIdentity(...);
   *   }
   *   catch (Pib::Error&) {
   *     ...
   *   }
   *
   * An Identity instance created using the constructor is invalid. Calling a
   * member method on an invalid Identity instance may cause an std::domain_error.
   */
  Identity();

  /// @brief Get the name of the identity.
  const Name&
  getName() const;

  /**
   * @brief Get a key with id @p keyId.
   *
   * @param keyId The id of the key to get.
   * @throw Pib::Error if the key does not exist.
   */
  Key
  getKey(const name::Component& keyId) const;

  /// @brief Get all the keys for this Identity.
  const KeyContainer&
  getKeys() const;

  /**
   * @brief Get the default key for this Identity.
   *
   * @throws Pib::Error if the default key does not exist.
   */
  Key&
  getDefaultKey() const;

  /// @brief Check if the Identity instance is valid
  operator bool() const;

  /// @brief Check if the Identity instance is invalid
  bool
  operator!() const;

NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private

  /**
   * @brief Add a key.
   *
   * If the key already exists, do nothing.
   *
   * If no default key is set before, the new key will be set as the default key of the identity.
   *
   * @param publicKey The public key to add.
   * @param keyId The key id component of the new key to add.
   *              By default, the keyId will be set to the hash of the public key bits.
   * @return the added key or existing key with the same key id.
   */
  Key
  addKey(const v1::PublicKey& publicKey, const name::Component& keyId = EMPTY_KEY_ID);

  /**
   * @brief Remove a key.
   *
   * @param keyId The key id component of the key to delete.
   */
  void
  removeKey(const name::Component& keyId);

  /**
   * @brief Set the key with id @p keyId as the default key.
   *
   * @param keyId The key id component of the default key.
   * @return The default key
   * @throws Pib::Error if the key does not exist.
   */
  Key&
  setDefaultKey(const name::Component& keyId);

  /**
   * @brief Set the default key.
   *
   * If the key does not exist, add the key and set it as the default of the Identity.
   * If the key exists, simply set it as the default key of the Identity.
   *
   * @param publicKey The public key to add.
   * @param keyId The key id component of the default key.
   * @return the default key
   */
  Key&
  setDefaultKey(const v1::PublicKey& publicKey, const name::Component& keyId = EMPTY_KEY_ID);

NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  /**
   * @brief Create an Identity with @p identityName.
   *
   * @param identityName The name of the Identity.
   * @param impl The backend implementation.
   * @param needInit If true, create the identity in backend when the identity does not exist.
   *                 Otherwise, throw Pib::Error when the identity does not exist.
   */
  Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);

  /**
   * @brief Check the validity of this instance
   *
   * @throws std::domain_error if the instance is invalid
   */
  void
  validityCheck() const;

public:
  /**
   * @brief The default value of keyId when add a new key.
   *
   * An empty keyId implies that the key digest should be used as the actual keyId.
   */
  static const name::Component EMPTY_KEY_ID;

private:
  Name m_name;

  mutable bool m_hasDefaultKey;
  mutable Key m_defaultKey;

  mutable bool m_needRefreshKeys;
  mutable KeyContainer m_keys;

  shared_ptr<PibImpl> m_impl;
};

} // namespace security
} // namespace ndn

#endif // NDN_SECURITY_PIB_IDENTITY_HPP
