/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, Regents of the University of California
 *
 * NAC 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.
 *
 * NAC 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 NAC library authors and contributors.
 */

#ifndef NDN_NAC_ENCRYPTOR_HPP
#define NDN_NAC_ENCRYPTOR_HPP

#include "common.hpp"
#include "encrypted-content.hpp"

namespace ndn {
namespace nac {

/**
 * @brief NAC Encryptor
 *
 * Encryptor encrypts the requested content and returns ``EncryptedContent`` element.
 */
class Encryptor
{
public:
  /**
   * @param accessPrefix  NAC prefix to fetch KEK (e.g., /access/prefix/NAC/data/subset)
   * @param ckPrefix      Prefix under which Content Keys will be generated
   *                      (each will have unique version appended)
   * @param ckDataSigningInfo  SigningInfo parameters to sign CK Data
   * @param onFailure     Callback to notify application of a failure to create CK data
   *                      (failed to fetch KEK, failed to encrypt with KEK, etc.).
   *                      Note that Encryptor will continue trying to retrieve KEK until success
   *                      (each attempt separated by `RETRY_DELAY_KEK_RETRIEVAL`) and @p onFailure
   *                      may be called multiple times.
   * @param validator     Validation policy to ensure correctness of KEK
   * @param keyChain      KeyChain
   * @param face          Face that will be used to fetch KEK and publish CK data
   */
  Encryptor(const Name& accessPrefix,
            const Name& ckPrefix, SigningInfo ckDataSigningInfo,
            const ErrorCallback& onFailure,
            Validator& validator, KeyChain& keyChain, Face& face);

  ~Encryptor();

  /**
   * Synchronously encrypt supplied data
   *
   * If KEK has not been fetched already, this method will trigger async fetching of it.
   * After KEK successfully fetched, CK data will be automatically published.
   *
   * @todo For now, CK is being published in InMemoryStorage and can be fetched only while
   *       Encryptor instance is alive.
   *
   * The actual encryption is done synchronously, but the exact KDK name is not known
   * until KEK is fetched.
   *
   * Note that if the KDK name is already known, this method will call onReady right away.
   *
   * @return Encrypted content
   */
  EncryptedContent
  encrypt(const uint8_t* data, size_t size);

  /**
   * @brief Create a new content key and publish the corresponding CK data
   *
   * @todo Ensure that CK data packet for the old CK is published, when CK updated
   *       before KEK fetched
   */
  void
  regenerateCk();

public: // accessor interface for published data packets

  /** @return{ number of packets stored in in-memory storage }
   */
  size_t
  size() const
  {
    return m_ims.size();
  }

  /** @brief Returns begin iterator of the in-memory storage ordered by
   *  name with digest
   *
   *  @return{ const_iterator pointing to the beginning of m_cache }
   */
  InMemoryStorage::const_iterator
  begin() const
  {
    return m_ims.begin();
  }

  /** @brief Returns end iterator of the in-memory storage ordered by
   *  name with digest
   *
   *  @return{ const_iterator pointing to the end of m_cache }
   */
  InMemoryStorage::const_iterator
  end() const
  {
    return m_ims.end();
  }

private:
  void
  retryFetchingKek();

  void
  fetchKekAndPublishCkData(const std::function<void()>& onReady,
                           const ErrorCallback& onFailure,
                           size_t nTriesLeft);

  bool
  makeAndPublishCkData(const ErrorCallback& onFailure);

PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  Name m_accessPrefix;
  Name m_ckPrefix;
  Name m_ckName;
  Buffer m_ckBits;
  SigningInfo m_ckDataSigningInfo;

  bool m_isKekRetrievalInProgress;
  optional<Data> m_kek;
  ErrorCallback m_onFailure;

  InMemoryStoragePersistent m_ims; // for encrypted CKs
  const RegisteredPrefixId* m_ckRegId = nullptr;
  const PendingInterestId* m_kekPendingInterest = nullptr;

  KeyChain& m_keyChain;
  Face& m_face;
  Scheduler m_scheduler;
};

} // namespace nac
} // namespace ndn

#endif // NDN_NAC_ENCRYPTOR_HPP
