// 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.

#include "pw_ring_buffer/prefixed_entry_ring_buffer.h"

#include <algorithm>
#include <cstring>

#include "pw_assert/light.h"
#include "pw_varint/varint.h"

namespace pw {
namespace ring_buffer {

using std::byte;
using Reader = PrefixedEntryRingBufferMulti::Reader;

void PrefixedEntryRingBufferMulti::Clear() {
  write_idx_ = 0;
  for (Reader& reader : readers_) {
    reader.read_idx = 0;
    reader.entry_count = 0;
  }
}

Status PrefixedEntryRingBufferMulti::SetBuffer(std::span<byte> buffer) {
  if ((buffer.data() == nullptr) ||  //
      (buffer.size_bytes() == 0) ||  //
      (buffer.size_bytes() > kMaxBufferBytes)) {
    return Status::InvalidArgument();
  }

  buffer_ = buffer.data();
  buffer_bytes_ = buffer.size_bytes();

  Clear();
  return OkStatus();
}

Status PrefixedEntryRingBufferMulti::AttachReader(Reader& reader) {
  if (reader.buffer != nullptr) {
    return Status::InvalidArgument();
  }
  reader.buffer = this;

  // Note that a newly attached reader sees the buffer as empty,
  // and is not privy to entries pushed before being attached.
  reader.read_idx = write_idx_;
  reader.entry_count = 0;
  readers_.push_back(reader);
  return OkStatus();
}

Status PrefixedEntryRingBufferMulti::DetachReader(Reader& reader) {
  if (reader.buffer != this) {
    return Status::InvalidArgument();
  }
  reader.buffer = nullptr;
  reader.read_idx = 0;
  reader.entry_count = 0;
  readers_.remove(reader);
  return OkStatus();
}

Status PrefixedEntryRingBufferMulti::InternalPushBack(
    std::span<const byte> data,
    byte user_preamble_data,
    bool drop_elements_if_needed) {
  if (buffer_ == nullptr) {
    return Status::FailedPrecondition();
  }
  if (data.size_bytes() == 0) {
    return Status::InvalidArgument();
  }

  // Prepare the preamble, and ensure we can fit the preamble and entry.
  byte varint_buf[kMaxEntryPreambleBytes];
  size_t varint_bytes = varint::Encode<size_t>(data.size_bytes(), varint_buf);
  size_t total_write_bytes =
      (user_preamble_ ? 1 : 0) + varint_bytes + data.size_bytes();
  if (buffer_bytes_ < total_write_bytes) {
    return Status::OutOfRange();
  }

  if (drop_elements_if_needed) {
    // PushBack() case: evict items as needed.
    // Drop old entries until we have space for the new entry.
    while (RawAvailableBytes() < total_write_bytes) {
      InternalPopFrontAll();
    }
  } else if (RawAvailableBytes() < total_write_bytes) {
    // TryPushBack() case: don't evict items.
    return Status::ResourceExhausted();
  }

  // Write the new entry into the ring buffer.
  if (user_preamble_) {
    RawWrite(std::span(&user_preamble_data, sizeof(user_preamble_data)));
  }
  RawWrite(std::span(varint_buf, varint_bytes));
  RawWrite(data);

  // Update all readers of the new count.
  for (Reader& reader : readers_) {
    reader.entry_count++;
  }
  return OkStatus();
}

auto GetOutput(std::span<byte> data_out, size_t* write_index) {
  return [data_out, write_index](std::span<const byte> src) -> Status {
    size_t copy_size = std::min(data_out.size_bytes(), src.size_bytes());

    memcpy(data_out.data() + *write_index, src.data(), copy_size);
    *write_index += copy_size;

    return (copy_size == src.size_bytes()) ? OkStatus()
                                           : Status::ResourceExhausted();
  };
}

Status PrefixedEntryRingBufferMulti::InternalPeekFront(Reader& reader,
                                                       std::span<byte> data,
                                                       size_t* bytes_read) {
  *bytes_read = 0;
  return InternalRead(reader, GetOutput(data, bytes_read), false);
}

Status PrefixedEntryRingBufferMulti::InternalPeekFront(Reader& reader,
                                                       ReadOutput output) {
  return InternalRead(reader, output, false);
}

Status PrefixedEntryRingBufferMulti::InternalPeekFrontWithPreamble(
    Reader& reader, std::span<byte> data, size_t* bytes_read) {
  *bytes_read = 0;
  return InternalRead(reader, GetOutput(data, bytes_read), true);
}

Status PrefixedEntryRingBufferMulti::InternalPeekFrontWithPreamble(
    Reader& reader, ReadOutput output) {
  return InternalRead(reader, output, true);
}

// T should be similar to Status (*read_output)(std::span<const byte>)
template <typename T>
Status PrefixedEntryRingBufferMulti::InternalRead(Reader& reader,
                                                  T read_output,
                                                  bool get_preamble) {
  if (buffer_ == nullptr) {
    return Status::FailedPrecondition();
  }
  if (reader.entry_count == 0) {
    return Status::OutOfRange();
  }

  // Figure out where to start reading (wrapped); accounting for preamble.
  EntryInfo info = FrontEntryInfo(reader);
  size_t read_bytes = info.data_bytes;
  size_t data_read_idx = reader.read_idx;
  if (get_preamble) {
    read_bytes += info.preamble_bytes;
  } else {
    data_read_idx = IncrementIndex(data_read_idx, info.preamble_bytes);
  }

  // Read bytes, stopping at the end of the buffer if this entry wraps.
  size_t bytes_until_wrap = buffer_bytes_ - data_read_idx;
  size_t bytes_to_copy = std::min(read_bytes, bytes_until_wrap);
  Status status =
      read_output(std::span(buffer_ + data_read_idx, bytes_to_copy));

  // If the entry wrapped, read the remaining bytes.
  if (status.ok() && (bytes_to_copy < read_bytes)) {
    status = read_output(std::span(buffer_, read_bytes - bytes_to_copy));
  }
  return status;
}

void PrefixedEntryRingBufferMulti::InternalPopFrontAll() {
  // Forcefully pop all readers. Find the slowest reader, which must have
  // the highest entry count, then pop all readers that have the same count.
  //
  // It is expected that InternalPopFrontAll is called only when there is
  // something to pop from at least one reader. If no readers exist, or all
  // readers are caught up, this function will assert.
  size_t entry_count = GetSlowestReader().entry_count;
  PW_DASSERT(entry_count != 0);
  // Otherwise, pop the readers that have the largest value.
  for (Reader& reader : readers_) {
    if (reader.entry_count == entry_count) {
      reader.PopFront();
    }
  }
}

Reader& PrefixedEntryRingBufferMulti::GetSlowestReader() {
  // Readers are guaranteed to be before the writer pointer (the class enforces
  // this on every read/write operation that forces the write pointer ahead of
  // an existing reader). To determine the slowest reader, we consider three
  // scenarios:
  //
  // In all below cases, WH is the write-head, and R# are readers, with R1
  // representing the slowest reader.
  // [[R1 R2 R3 WH]] => Right-hand writer, slowest reader is left-most reader.
  // [[WH R1 R2 R3]] => Left-hand writer, slowest reader is left-most reader.
  // [[R3 WH R1 R2]] => Middle-writer, slowest reader is left-most reader after
  // writer.
  //
  // Formally, choose the left-most reader after the writer (ex.2,3), but if
  // that doesn't exist, choose the left-most reader before the writer (ex.1).
  PW_DASSERT(readers_.size() > 0);
  Reader* slowest_reader_after_writer = nullptr;
  Reader* slowest_reader_before_writer = nullptr;
  for (Reader& reader : readers_) {
    if (reader.read_idx < write_idx_) {
      if (!slowest_reader_before_writer ||
          reader.read_idx < slowest_reader_before_writer->read_idx) {
        slowest_reader_before_writer = &reader;
      }
    } else {
      if (!slowest_reader_after_writer ||
          reader.read_idx < slowest_reader_after_writer->read_idx) {
        slowest_reader_after_writer = &reader;
      }
    }
  }
  return *(slowest_reader_after_writer ? slowest_reader_after_writer
                                       : slowest_reader_before_writer);
}

Status PrefixedEntryRingBufferMulti::Dering() {
  if (buffer_ == nullptr || readers_.size() == 0) {
    return Status::FailedPrecondition();
  }

  // Check if by luck we're already deringed.
  Reader* slowest_reader = &GetSlowestReader();
  if (slowest_reader->read_idx == 0) {
    return OkStatus();
  }

  auto buffer_span = std::span(buffer_, buffer_bytes_);
  std::rotate(buffer_span.begin(),
              buffer_span.begin() + slowest_reader->read_idx,
              buffer_span.end());

  // If the new index is past the end of the buffer,
  // alias it back (wrap) to the start of the buffer.
  if (write_idx_ < slowest_reader->read_idx) {
    write_idx_ += buffer_bytes_;
  }
  write_idx_ -= slowest_reader->read_idx;

  for (Reader& reader : readers_) {
    if (&reader == slowest_reader) {
      continue;
    }
    if (reader.read_idx < slowest_reader->read_idx) {
      reader.read_idx += buffer_bytes_;
    }
    reader.read_idx -= slowest_reader->read_idx;
  }

  slowest_reader->read_idx = 0;
  return OkStatus();
}

Status PrefixedEntryRingBufferMulti::InternalPopFront(Reader& reader) {
  if (buffer_ == nullptr) {
    return Status::FailedPrecondition();
  }
  if (reader.entry_count == 0) {
    return Status::OutOfRange();
  }

  // Advance the read pointer past the front entry to the next one.
  EntryInfo info = FrontEntryInfo(reader);
  size_t entry_bytes = info.preamble_bytes + info.data_bytes;
  size_t prev_read_idx = reader.read_idx;
  reader.read_idx = IncrementIndex(prev_read_idx, entry_bytes);
  reader.entry_count--;
  return OkStatus();
}

size_t PrefixedEntryRingBufferMulti::InternalFrontEntryDataSizeBytes(
    Reader& reader) {
  if (reader.entry_count == 0) {
    return 0;
  }
  return FrontEntryInfo(reader).data_bytes;
}

size_t PrefixedEntryRingBufferMulti::InternalFrontEntryTotalSizeBytes(
    Reader& reader) {
  if (reader.entry_count == 0) {
    return 0;
  }
  EntryInfo info = FrontEntryInfo(reader);
  return info.preamble_bytes + info.data_bytes;
}

PrefixedEntryRingBufferMulti::EntryInfo
PrefixedEntryRingBufferMulti::FrontEntryInfo(Reader& reader) {
  // Entry headers consists of: (optional prefix byte, varint size, data...)

  // Read the entry header; extract the varint and it's size in bytes.
  byte varint_buf[kMaxEntryPreambleBytes];
  RawRead(varint_buf,
          IncrementIndex(reader.read_idx, user_preamble_ ? 1 : 0),
          kMaxEntryPreambleBytes);
  uint64_t entry_size;
  size_t varint_size = varint::Decode(varint_buf, &entry_size);

  EntryInfo info = {};
  info.preamble_bytes = (user_preamble_ ? 1 : 0) + varint_size;
  info.data_bytes = entry_size;
  return info;
}

// Comparisons ordered for more probable early exits, assuming the reader is
// not far behind the writer compared to the size of the ring.
size_t PrefixedEntryRingBufferMulti::RawAvailableBytes() {
  // Compute slowest reader.
  // TODO: Alternatively, the slowest reader could be actively mantained on
  // every read operation, but reads are more likely than writes.
  if (readers_.size() == 0) {
    return buffer_bytes_;
  }

  size_t read_idx = GetSlowestReader().read_idx;
  // Case: Not wrapped.
  if (read_idx < write_idx_) {
    return buffer_bytes_ - (write_idx_ - read_idx);
  }
  // Case: Wrapped
  if (read_idx > write_idx_) {
    return read_idx - write_idx_;
  }
  // Case: Matched read and write heads; empty or full.
  for (Reader& reader : readers_) {
    if (reader.read_idx == read_idx && reader.entry_count != 0) {
      return 0;
    }
  }
  return buffer_bytes_;
}

void PrefixedEntryRingBufferMulti::RawWrite(std::span<const std::byte> source) {
  // Write until the end of the source or the backing buffer.
  size_t bytes_until_wrap = buffer_bytes_ - write_idx_;
  size_t bytes_to_copy = std::min(source.size(), bytes_until_wrap);
  memcpy(buffer_ + write_idx_, source.data(), bytes_to_copy);

  // If there wasn't space in the backing buffer, wrap to the front.
  if (bytes_to_copy < source.size()) {
    memcpy(
        buffer_, source.data() + bytes_to_copy, source.size() - bytes_to_copy);
  }
  write_idx_ = IncrementIndex(write_idx_, source.size());
}

void PrefixedEntryRingBufferMulti::RawRead(byte* destination,
                                           size_t source_idx,
                                           size_t length_bytes) {
  // Read the pre-wrap bytes.
  size_t bytes_until_wrap = buffer_bytes_ - source_idx;
  size_t bytes_to_copy = std::min(length_bytes, bytes_until_wrap);
  memcpy(destination, buffer_ + source_idx, bytes_to_copy);

  // Read the post-wrap bytes, if needed.
  if (bytes_to_copy < length_bytes) {
    memcpy(destination + bytes_to_copy, buffer_, length_bytes - bytes_to_copy);
  }
}

size_t PrefixedEntryRingBufferMulti::IncrementIndex(size_t index,
                                                    size_t count) {
  // Note: This doesn't use modulus (%) since the branch is cheaper, and we
  // guarantee that count will never be greater than buffer_bytes_.
  index += count;
  if (index > buffer_bytes_) {
    index -= buffer_bytes_;
  }
  return index;
}

}  // namespace ring_buffer
}  // namespace pw
