#ifndef ANDROID_PDX_RPC_PAYLOAD_H_
#define ANDROID_PDX_RPC_PAYLOAD_H_

#include <iterator>

#include <pdx/client.h>
#include <pdx/rpc/message_buffer.h>
#include <pdx/service.h>

namespace android {
namespace pdx {
namespace rpc {

// Implements the payload interface, required by Serialize/Deserialize, on top
// of a thread-local MessageBuffer.
template <typename Slot>
class MessagePayload {
 public:
  using BufferType = typename MessageBuffer<Slot>::BufferType;
  using ValueType = typename MessageBuffer<Slot>::ValueType;

  // Constructs a MessagePayload with an empty TLS buffer.
  MessagePayload()
      : buffer_(MessageBuffer<Slot>::GetEmptyBuffer()),
        cursor_(buffer_.begin()),
        const_cursor_(buffer_.cbegin()) {}

  // Returns a reference to the cursor iterator to be used during serialization
  // into the underlying MessageBuffer.
  typename BufferType::iterator& Cursor() { return cursor_; }

  // Returns a reference to the const cursor iterator at the beginning of the
  // underlying MessageBuffer.
  typename BufferType::const_iterator& ConstCursor() { return const_cursor_; }

  // Returns a const iterator marking the end of the underlying MessageBuffer.
  typename BufferType::const_iterator ConstEnd() { return buffer_.cend(); }

  // Resizes the underlying MessageBuffer and sets the cursor to the beginning.
  void Resize(std::size_t size) {
    buffer_.resize(size);
    cursor_ = buffer_.begin();
    const_cursor_ = buffer_.cbegin();
  }

  // Resets the read cursor so that data can be read from the buffer again.
  void Rewind() { const_cursor_ = buffer_.cbegin(); }

  // Adds |size| bytes to the size of the underlying MessageBuffer and positions
  // the cursor at the beginning of the extended region.
  void Extend(std::size_t size) {
    const std::size_t offset = buffer_.size();
    buffer_.resize(offset + size);
    cursor_ = buffer_.begin() + offset;
    const_cursor_ = buffer_.cbegin() + offset;
  }

  // Clears the underlying MessageBuffer and sets the cursor to the beginning.
  void Clear() {
    buffer_.clear();
    cursor_ = buffer_.begin();
    const_cursor_ = buffer_.cbegin();
  }

  ValueType* Data() { return buffer_.data(); }
  const ValueType* Data() const { return buffer_.data(); }
  std::size_t Size() const { return buffer_.size(); }
  std::size_t Capacity() const { return buffer_.capacity(); }

 private:
  BufferType& buffer_;
  typename BufferType::iterator cursor_;
  typename BufferType::const_iterator const_cursor_;

  MessagePayload(const MessagePayload<Slot>&) = delete;
  void operator=(const MessagePayload<Slot>&) = delete;
};

// Implements the payload interface for service-side RPCs. Handles translating
// between remote and local handle spaces automatically.
template <typename Slot>
class ServicePayload : public MessagePayload<Slot>,
                       public MessageWriter,
                       public MessageReader {
 public:
  ServicePayload(Message& message) : message_(message) {}

  // MessageWriter
  void* GetNextWriteBufferSection(size_t size) override {
    this->Extend(size);
    return &*this->Cursor();
  }

  OutputResourceMapper* GetOutputResourceMapper() override { return &message_; }

  // MessageReader
  BufferSection GetNextReadBufferSection() override {
    return {&*this->ConstCursor(), &*this->ConstEnd()};
  }

  void ConsumeReadBufferSectionData(const void* new_start) override {
    std::advance(this->ConstCursor(),
                 PointerDistance(new_start, &*this->ConstCursor()));
  }

  InputResourceMapper* GetInputResourceMapper() override { return &message_; }

 private:
  Message& message_;
};

// Implements the payload interface for client-side RPCs. Handles gathering file
// handles to be sent over IPC automatically.
template <typename Slot>
class ClientPayload : public MessagePayload<Slot>,
                      public MessageWriter,
                      public MessageReader {
 public:
  using ContainerType =
      MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>;
  using BufferType = typename ContainerType::BufferType;

  ClientPayload(Transaction& transaction) : transaction_{transaction} {}

  // MessageWriter
  void* GetNextWriteBufferSection(size_t size) override {
    this->Extend(size);
    return &*this->Cursor();
  }

  OutputResourceMapper* GetOutputResourceMapper() override {
    return &transaction_;
  }

  // MessageReader
  BufferSection GetNextReadBufferSection() override {
    return {&*this->ConstCursor(), &*this->ConstEnd()};
  }

  void ConsumeReadBufferSectionData(const void* new_start) override {
    std::advance(this->ConstCursor(),
                 PointerDistance(new_start, &*this->ConstCursor()));
  }

  InputResourceMapper* GetInputResourceMapper() override {
    return &transaction_;
  }

 private:
  Transaction& transaction_;
};

}  // namespace rpc
}  // namespace pdx
}  // namespace android

#endif  // ANDROID_PDX_RPC_PAYLOAD_H_
