/* -*- 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_CXX_SECURITY_TRANSFORM_BASE_HPP
#define NDN_CXX_SECURITY_TRANSFORM_BASE_HPP

#include "../../common.hpp"
#include <vector>

namespace ndn {
namespace security {
namespace transform {

/**
 * @file transform-base.hpp
 *
 * There are three types of module in a transformation chain: Source, Transform, and Sink.
 * The ideal usage of the transformation would be:
 *
 *   source(...) >> transform1(...) >> transform2(...) >> sink(...);
 *
 * When error happens in a module, the module will throw out a transform::Error, one
 * can get the location of the module through the getIndex() method of transform::Error.
 */

/**
 * @brief Base class of transformation error
 */
class Error : public std::runtime_error
{
public:
  Error(size_t index, const std::string& what);

  size_t
  getIndex() const
  {
    return m_index;
  }

private:
  size_t m_index;
};

/**
 * @brief The downstream interface of a transformation module
 *
 * A module can accept input through this interface
 */
class Downstream
{
public:
  virtual
  ~Downstream() = default;

  /**
   * @brief Accept input data and perform transformation.
   *
   * An upstream module should call this method to write data into this module.
   * The written data will be transformed and the result will be written into the next
   * downstream module.
   *
   * An upstream module can keep calling this method to until end() is called, which
   * indicates the end of input.  After that, calling this method will cause Error.
   *
   * If a Downstream implementation expects structured input (e.g., hex decoding requires byte-pair),
   * it should not return less than size if final portion of input is not a complete record.
   *
   * @return number of bytes that has been written into this module
   * @throws Error if this module is closed or transformation error happens.
   */
  size_t
  write(const uint8_t* buf, size_t size);

  /**
   * @brief Close the input interface of a module.
   *
   * This method will notify this module that there is no more input and that the module
   * should finalize transformation.
   *
   * Although end() can be invoked multiple times, only the first invocation takes effect.
   */
  void
  end();

  /**
   * @brief Check if the input interface of a module is closed.
   */
  bool
  isEnd() const
  {
    return m_isEnd;
  }

  /**
   * @brief Set the module index.
   */
  void
  setIndex(size_t index)
  {
    m_index = index;
  }

  /**
   * @brief Get the module index.
   */
  size_t
  getIndex() const
  {
    return m_index;
  }

protected:
  Downstream();

private:
  /**
   * @brief Internal implementation of write method
   */
  virtual size_t
  doWrite(const uint8_t* buf, size_t size) = 0;

  /**
   * @brief Internal implementation of end method
   */
  virtual void
  doEnd() = 0;

private:
  bool m_isEnd;
  size_t m_index;
};

/**
 * @brief The upstream interface of a transformation module
 *
 * A module can construct subsequent transformation chain through this interface.
 */
class Upstream
{
public:
  virtual
  ~Upstream() = default;

protected:
  Upstream();

protected:
  /**
   * @brief connect to next transformation module
   */
  void
  appendChain(unique_ptr<Downstream> tail);

  Downstream*
  getNext()
  {
    return m_next.get();
  }

protected:
  unique_ptr<Downstream> m_next;
};

/**
 * @brief Abstraction of an intermediate transformation module
 */
class Transform : public Upstream,
                  public Downstream,
                  noncopyable
{
protected:
  typedef std::vector<uint8_t> OBuffer;

  Transform();

  /**
   * @brief Read the content from output buffer and write it into next module.
   *
   * It is not guaranteed that all the content in output buffer will be flushed to next module.
   */
  void
  flushOutputBuffer();

  /**
   * @brief Read the all the content from output buffer and write it into next module.
   * @post isOutputBufferEmpty() returns true.
   */
  void
  flushAllOutput();

  /**
   * @brief Set output buffer to @p buffer
   */
  void
  setOutputBuffer(unique_ptr<OBuffer> buffer);

  /**
   * @brief Check if output buffer is empty
   */
  bool
  isOutputBufferEmpty() const;

private:

  /**
   * @brief Abstraction of data processing in an intermediate module
   */
  virtual size_t
  doWrite(const uint8_t* data, size_t dataLen) final;

  /**
   * @brief Finalize transformation in this module
   *
   * This method will not return until all transformation result is written into next module
   */
  virtual void
  doEnd() final;

  /**
   * @brief Process before transformation.
   *
   * @pre output buffer is empty.
   *
   * This method is invoked before every convert(...) invocation.
   *
   * This implementation does nothing.  A subclass can override this method to perform
   * specific pre-transformation procedure, e.g., read partial transformation results into
   * output buffer.
   */
  virtual void
  preTransform();

  /**
   * @brief Convert input @p data.
   *
   * @return The number of input bytes that have been accepted by the converter.
   */
  virtual size_t
  convert(const uint8_t* data, size_t dataLen) = 0;

  /**
   * @brief Finalize the transformation.
   *
   * This implementation only flushes content in output buffer into next module.
   * A subclass can override this method to perform specific finalization procedure, i.e.,
   * finalize the transformation and flush the result into next module.
   */
  virtual void
  finalize();

private:
  unique_ptr<OBuffer> m_oBuffer;
  size_t m_outputOffset;
};

/**
 * @brief Abstraction of the transformation sink module
 *
 * This module does not have next module and can only accept input data
 */
class Sink : public Downstream,
             noncopyable
{
};

/**
 * @brief Abstraction of the transformation source module
 *
 * This module can only accept input data from constructor
 */
class Source : public Upstream,
               noncopyable
{
public:
  /**
   * @brief Connect to an intermediate transformation module.
   */
  Source&
  operator>>(unique_ptr<Transform> transform);

  /**
   * @brief Connect to the last transformation module.
   *
   * This method will trigger the source to pump data into the transformation pipeline.
   */
  void
  operator>>(unique_ptr<Sink> sink);

protected:
  Source();

  /**
   * @brief Pump all data into next transformation module.
   */
  void
  pump();

  /**
   * @brief Get the source module index (should always be 0).
   */
  size_t
  getIndex() const
  {
    return 0;
  }

private:
  /**
   * @brief Internal implementation of pump().
   */
  virtual void
  doPump() = 0;

private:
  size_t m_nModules; // count of modules in the chain starting from this Source
};

} // namespace transform
} // namespace security
} // namespace ndn

#endif // NDN_CXX_SECURITY_TRANSFORM_BASE_HPP
