/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2021 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_CXX_SECURITY_PIB_KEY_CONTAINER_HPP
#define NDN_CXX_SECURITY_PIB_KEY_CONTAINER_HPP

#include "ndn-cxx/security/pib/key.hpp"

#include <iterator>
#include <set>
#include <unordered_map>

namespace ndn {
namespace security {
namespace pib {

class PibImpl;

namespace detail {
class KeyImpl;
class IdentityImpl;
} // namespace detail

/**
 * @brief Container of keys of an identity
 *
 * The container is used to search/enumerate keys of an identity.
 * The container can be created only by detail::IdentityImpl.
 */
class KeyContainer : noncopyable
{
public:
  class const_iterator
  {
  public:
    using iterator_category = std::forward_iterator_tag;
    using value_type        = const Key;
    using difference_type   = std::ptrdiff_t;
    using pointer           = value_type*;
    using reference         = value_type&;

    const_iterator();

    Key
    operator*();

    const_iterator&
    operator++();

    const_iterator
    operator++(int);

    bool
    operator==(const const_iterator& other);

    bool
    operator!=(const const_iterator& other);

  private:
    const_iterator(std::set<Name>::const_iterator it, const KeyContainer& container);

  private:
    std::set<Name>::const_iterator m_it;
    const KeyContainer* m_container;

    friend class KeyContainer;
  };

  using iterator = const_iterator;

public:
  const_iterator
  begin() const;

  const_iterator
  end() const;

  const_iterator
  find(const Name& keyName) const;

  size_t
  size() const;

  /**
   * @brief Add @p key of @p keyLen bytes with @p keyName into the container
   * @throw std::invalid_argument @p keyName does not match the identity
   *
   * If a key with the same name already exists, overwrite the key.
   */
  Key
  add(const uint8_t* key, size_t keyLen, const Name& keyName);

  /**
   * @brief Remove a key with @p keyName from the container
   * @throw std::invalid_argument @p keyName does not match the identity
   */
  void
  remove(const Name& keyName);

  /**
   * @brief Get a key with @p keyName from the container
   * @throw std::invalid_argument @p keyName does not match the identity
   * @throw Pib::Error the key does not exist
   */
  Key
  get(const Name& keyName) const;

  /**
   * @brief Check if the container is consistent with the backend storage
   *
   * @note this method is heavyweight and should be used in debugging mode only.
   */
  bool
  isConsistent() const;

NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  /**
   * @brief Create key container for @p identity
   * @param pibImpl The PIB backend implementation.
   */
  KeyContainer(const Name& identity, shared_ptr<PibImpl> pibImpl);

  const std::set<Name>&
  getKeyNames() const
  {
    return m_keyNames;
  }

  const std::unordered_map<Name, shared_ptr<detail::KeyImpl>>&
  getLoadedKeys() const
  {
    return m_keys;
  }

private:
  Name m_identity;
  std::set<Name> m_keyNames;
  /// @brief Cache of loaded detail::KeyImpl.
  mutable std::unordered_map<Name, shared_ptr<detail::KeyImpl>> m_keys;

  shared_ptr<PibImpl> m_pib;

#ifndef DOXYGEN
  friend detail::IdentityImpl;
#endif
};

} // namespace pib

using pib::KeyContainer;

} // namespace security
} // namespace ndn

#endif // NDN_CXX_SECURITY_PIB_KEY_CONTAINER_HPP
