// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once

#include <cstddef>

#include "pw_span/span.h"
#include "pw_status/status.h"

namespace pw {
namespace ring_buffer {

// A circular ring buffer for arbitrary length data entries. Each PushBack()
// produces a buffer entry. Each entry consists of a preamble followed by an
// arbitrary length data chunk. The preamble is comprised of an optional user
// preamble byte and an always present varint. The varint encodes the number of
// bytes in the data chunk.
//
// The ring buffer holds the most recent entries stored in the buffer. Once
// filled to capacity, incoming entries bump out the oldest entries to make
// room. Entries are internally wrapped around as needed.
class PrefixedEntryRingBuffer {
 public:
  typedef Status (*ReadOutput)(span<const std::byte>);

  PrefixedEntryRingBuffer(bool user_preamble = false)
      : buffer_(nullptr),
        buffer_bytes_(0),
        write_idx_(0),
        read_idx_(0),
        entry_count_(0),
        user_preamble_(user_preamble) {}

  // Set the raw buffer to be used by the ring buffer.
  //
  // Return values:
  // OK - successfully set the raw buffer.
  // INVALID_ARGUMENT - Argument was nullptr, size zero, or too large.
  Status SetBuffer(span<std::byte> buffer);

  // Removes all data from the ring buffer.
  void Clear();

  // Write a chunk of data to the ring buffer. If available space is less than
  // size of data chunk to be written then silently pop and discard oldest
  // stored data chunks until space is available.
  //
  // Preamble argument is a caller-provided value prepended to the front of the
  // entry. It is only used if user_preamble was set at class construction
  // time.
  //
  // Return values:
  // OK - Data successfully written to the ring buffer.
  // INVALID_ARGUMENT - Size of data to write is zero bytes
  // FAILED_PRECONDITION - Buffer not initialized.
  // OUT_OF_RANGE - Size of data is greater than buffer size.
  Status PushBack(span<const std::byte> data,
                  std::byte user_preamble_data = std::byte(0)) {
    return InternalPushBack(data, user_preamble_data, true);
  }

  // Write a chunk of data to the ring buffer if there is space available.
  //
  // Preamble argument is a caller-provided value prepended to the front of the
  // entry. It is only used if user_preamble was set at class construction
  // time.
  //
  // Return values:
  // OK - Data successfully written to the ring buffer.
  // INVALID_ARGUMENT - Size of data to write is zero bytes
  // FAILED_PRECONDITION - Buffer not initialized.
  // OUT_OF_RANGE - Size of data is greater than buffer size.
  // RESOURCE_EXHAUSTED - The ring buffer doesn't have space for the data
  // without popping off existing elements.
  Status TryPushBack(span<const std::byte> data,
                     std::byte user_preamble_data = std::byte(0)) {
    return InternalPushBack(data, user_preamble_data, false);
  }

  // Read the oldest stored data chunk of data from the ring buffer to
  // the provided destination span. The number of bytes read is written to
  // bytes_read
  //
  // Return values:
  // OK - Data successfully read from the ring buffer.
  // FAILED_PRECONDITION - Buffer not initialized.
  // OUT_OF_RANGE - No entries in ring buffer to read.
  // RESOURCE_EXHAUSTED - Destination data span was smaller number of bytes than
  // the data size of the data chunk being read.  Available destination bytes
  // were filled, remaining bytes of the data chunk were ignored.
  Status PeekFront(span<std::byte> data, size_t* bytes_read);

  Status PeekFront(ReadOutput output);

  // Same as Read but includes the entry's preamble of optional user value and
  // the varint of the data size
  Status PeekFrontWithPreamble(span<std::byte> data, size_t* bytes_read);

  Status PeekFrontWithPreamble(ReadOutput output);

  // Pop and discard the oldest stored data chunk of data from the ring buffer.
  //
  // Return values:
  // OK - Data successfully read from the ring buffer.
  // FAILED_PRECONDITION - Buffer not initialized.
  // OUT_OF_RANGE - No entries in ring buffer to pop.
  Status PopFront();

  // Dering the buffer by reordering entries internally in the buffer by
  // rotating to have the oldest entry is at the lowest address/index with
  // newest entry at the highest address.
  //
  // Return values:
  // OK - Buffer data successfully deringed.
  // FAILED_PRECONDITION - Buffer not initialized.
  Status Dering();

  // Get the number of variable-length entries currently in the ring buffer.
  //
  // Return value:
  // Entry count.
  size_t EntryCount() { return entry_count_; }

  // Get the size in bytes of all the current entries in the ring buffer,
  // including preamble and data chunk.
  size_t TotalUsedBytes() { return buffer_bytes_ - RawAvailableBytes(); }

  // Get the size in bytes of the next chunk, not including preamble, to be
  // read.
  size_t FrontEntryDataSizeBytes();

  // Get the size in bytes of the next chunk, including preamble and data
  // chunk, to be read.
  size_t FrontEntryTotalSizeBytes();

 private:
  struct EntryInfo {
    size_t preamble_bytes;
    size_t data_bytes;
  };

  // Internal version of Read used by all the public interface versions. T
  // should be of type ReadOutput.
  template <typename T>
  Status InternalRead(T read_output, bool get_preamble);

  // Push back implementation, which optionally discards front elements to fit
  // the incoming element.
  Status InternalPushBack(span<const std::byte> data,
                          std::byte user_preamble_data,
                          bool pop_front_if_needed);

  // Get info struct with the size of the preamble and data chunk for the next
  // entry to be read.
  EntryInfo FrontEntryInfo();

  // Get the raw number of available bytes free in the ring buffer. This is
  // not available bytes for data, since there is a variable size preamble for
  // each entry.
  size_t RawAvailableBytes();

  // Do the basic write of the specified number of bytes starting at the last
  // write index of the ring buffer to the destination, handing any wrap-around
  // of the ring buffer. This is basic, raw operation with no safety checks.
  void RawWrite(span<const std::byte> source);

  // Do the basic read of the specified number of bytes starting at the given
  // index of the ring buffer to the destination, handing any wrap-around of
  // the ring buffer. This is basic, raw operation with no safety checks.
  void RawRead(std::byte* destination, size_t source_idx, size_t length_bytes);

  size_t IncrementIndex(size_t index, size_t count);

  std::byte* buffer_;
  size_t buffer_bytes_;

  size_t write_idx_;
  size_t read_idx_;
  size_t entry_count_;
  const bool user_preamble_;

  // Worst case size for the variable-sized preable that is prepended to
  // each entry.
  static constexpr size_t kMaxEntryPreambleBytes = sizeof(size_t) + 1;

  // Maximum bufer size allowed. Restricted to this to allow index aliasing to
  // not overflow.
  static constexpr size_t kMaxBufferBytes =
      std::numeric_limits<size_t>::max() / 2;
};

}  // namespace ring_buffer
}  // namespace pw
