/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, Regents of the University of California
 *
 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
 *
 * ndn-group-encrypt is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * ndn-group-encrypt 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * ndn-group-encrypt, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Prashanth Swaminathan <prashanthsw@gmail.com>
 * @author Yingdi Yu <yuyingdi@gmail.com>
 */

#ifndef NDN_GEP_PRODUCER_HPP
#define NDN_GEP_PRODUCER_HPP

#include "error-code.hpp"
#include "producer-db.hpp"

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/key-chain.hpp>

namespace ndn {
namespace gep {

// @brief Callback returns vector of Data contains content keys encrypted by E-KEYS
typedef function<void(const std::vector<Data>&)> ProducerEKeyCallback;

/**
 * @brief Manage content key and data encryption
 */
class Producer
{
public:
  struct KeyInfo
  {
    time::system_clock::TimePoint beginTimeslot;
    time::system_clock::TimePoint endTimeslot;
    Buffer keyBits;
  };

  struct KeyRequest
  {
    KeyRequest(size_t interests)
      : interestCount(interests)
    {
    }
    size_t interestCount;
    std::unordered_map<Name, size_t> repeatAttempts;
    std::vector<Data> encryptedKeys;
  };

public:
  /**
   * @brief Construct a producer
   *
   * A producer can produce data with a naming convention:
   *   /<@p prefix>/SAMPLES/<@p dataType>/[timestamp]
   *
   * The produced data packet is encrypted with a content key,
   * which is stored in a database at @p dbPath.
   *
   * A producer also need to produce data containing content key
   * encrypted with E-KEYs. A producer can retrieve E-KEYs through
   * @p face, and will re-try for at most @p repeatAttemps times when
   * E-KEY retrieval fails.
   */
  Producer(const Name& prefix,
           const Name& dataType,
           Face& face,
           const std::string& dbPath,
           uint8_t repeatAttempts = 3,
           const Link& keyRetrievalLink = NO_LINK);

  /**
   * @brief Create content key corresponding to @p timeslot
   *
   * This method will first check if the content key exists. For existing
   * content key, the method will return content key name directly.
   * If the key does not exist, the method will create one and encrypt
   * it using corresponding E-KEY. The encrypted content keys will be
   * passed back through @p callback. In case of any error, @p errorCallBack
   * will be invoked.
   */
  Name
  createContentKey(const time::system_clock::TimePoint& timeslot,
                   const ProducerEKeyCallback& callback,
                   const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);


  /**
   * @brief Produce an data packet encrypted using the content key corresponding @p timeslot
   *
   * This method encrypts @p content of @p contentLen with a content key covering
   * @p timeslot, and set @p data with the encrypted content and appropriate data name.
   * In case of any error, @p errorCallBack will be invoked.
   */
  void
  produce(Data& data,
          const time::system_clock::TimePoint& timeslot,
          const uint8_t* content,
          size_t contentLen,
          const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);

public:
  /**
   * @brief Default error callback
   *
   * @param code The error code.
   * @param msg The error msg.
   */
  static void
  defaultErrorCallBack(const ErrorCode& code, const std::string& msg);

private:
  /**
   * @brief Send interest for E-KEY
   *
   * This method simply construct DataCallback, NackCallback, TiemoutCallback using
   * @p timeslot, @p callback, and @p errorCallBack, and express @p interest with
   * the created callbacks.
   */
  void
  sendKeyInterest(const Interest& interest,
                  const time::system_clock::TimePoint& timeslot,
                  const ProducerEKeyCallback& callback,
                  const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);

  /**
   * @brief Handle received E-KEY retrieved using @p interest.
   *
   * This method first checks if the E-key contained in @p data fits @p timeslot.
   * If true, encrypt the C-KEY for @p timeslot using the E-KEY, if the retrieval for
   * all E-KEYs for the C-KEY have been done, invoke @p callback. Otherwise, narrow down
   * the search scope through revising exclude filter and re-express the interest. In case
   * of any error, invoke @p errorCallBack.
   */
  void
  handleCoveringKey(const Interest& interest,
                    const Data& data,
                    const time::system_clock::TimePoint& timeslot,
                    const ProducerEKeyCallback& callback,
                    const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);

  /**
   * @brief Handle timeout.
   *
   * Re-express @p interest if the number of retrials is less than max limit.
   * The DataCallback, NackCallback, TiemoutCallback are created using @p timeslot,
   * @p callback, and @p errorCallBack,
   */
  void
  handleTimeout(const Interest& interest,
                const time::system_clock::TimePoint& timeslot,
                const ProducerEKeyCallback& callback,
                const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);

  /**
   * @brief Handle @p nack for the E-KEY requested through @p interest.
   *
   * This method will decrease the outstanding E-KEY interest count for the C-Key
   * corresponding to @p timeCount.  When there is no outstanding interest, invoke
   * @p callback.
   */
  void
  handleNack(const Interest& interest,
             const lp::Nack& nack,
             const time::system_clock::TimePoint& timeslot,
             const ProducerEKeyCallback& callback,
             const ErrorCallBack& errorCallBack = Producer::defaultErrorCallBack);

  /**
   * @brief Decrease the count of outstanding E-KEY interests for C-KEY for @p timeCount
   *
   * If the count decrease to 0, invoke @p callback.
   */
  void
  updateKeyRequest(KeyRequest& keyRequest, uint64_t timeCount, const ProducerEKeyCallback& callback);

  /**
   * @brief Encrypts C-KEY for @p timeslot using @p encryptionKey of @p eKeyName
   *
   * Invoke @p callback if no more interests to process.
   * invoke @p errorCallback in case of any error.
   *
   * @return true if encryption succeeds, otherwise false.
   */
  bool
  encryptContentKey(const Buffer& encryptionKey,
                    const Name& eKeyName,
                    const time::system_clock::TimePoint& timeslot,
                    const ProducerEKeyCallback& callback,
                    const ErrorCallBack& errorCallback = Producer::defaultErrorCallBack);

public:
  static const Link NO_LINK;

private:
  Face& m_face;
  Name m_namespace;
  KeyChain m_keychain;
  std::unordered_map<Name, KeyInfo> m_ekeyInfo;
  std::unordered_map<uint64_t, KeyRequest> m_keyRequests;
  ProducerDB m_db;
  uint8_t m_maxRepeatAttempts;

  Link m_keyRetrievalLink;
};

} // namespace gep
} // namespace ndn

#endif // NDN_GEP_PRODUCER_HPP
