// Copyright 2021 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_multisink/multisink.h"

#include <cstring>

#include "pw_assert/check.h"
#include "pw_bytes/span.h"
#include "pw_function/function.h"
#include "pw_log/log.h"
#include "pw_result/result.h"
#include "pw_status/status.h"
#include "pw_status/try.h"
#include "pw_varint/varint.h"

namespace pw {
namespace multisink {

void MultiSink::HandleEntry(ConstByteSpan entry) {
  std::lock_guard lock(lock_);
  PW_DCHECK_OK(ring_buffer_.PushBack(entry, sequence_id_++));
  NotifyListeners();
}

void MultiSink::HandleDropped(uint32_t drop_count) {
  std::lock_guard lock(lock_);
  sequence_id_ += drop_count;
  NotifyListeners();
}

Status MultiSink::PopEntry(Drain& drain, const Drain::PeekedEntry& entry) {
  std::lock_guard lock(lock_);
  PW_DCHECK_PTR_EQ(drain.multisink_, this);

  // Ignore the call if the entry has been handled already.
  if (entry.sequence_id() == drain.last_handled_sequence_id_) {
    return OkStatus();
  }

  uint32_t next_entry_sequence_id;
  Status peek_status = drain.reader_.PeekFrontPreamble(next_entry_sequence_id);
  if (!peek_status.ok()) {
    // Ignore errors if the multisink is empty.
    if (peek_status.IsOutOfRange()) {
      return OkStatus();
    }
    return peek_status;
  }
  if (next_entry_sequence_id == entry.sequence_id()) {
    // A crash should not happen, since the peek was successful and `lock_` is
    // still held, there shouldn't be any modifications to the multisink in
    // between peeking and popping.
    PW_CHECK_OK(drain.reader_.PopFront());
    drain.last_handled_sequence_id_ = next_entry_sequence_id;
  }
  return OkStatus();
}

Result<ConstByteSpan> MultiSink::PeekOrPopEntry(
    Drain& drain,
    ByteSpan buffer,
    Request request,
    uint32_t& drop_count_out,
    uint32_t& entry_sequence_id_out) {
  size_t bytes_read = 0;
  entry_sequence_id_out = 0;
  drop_count_out = 0;

  std::lock_guard lock(lock_);
  PW_DCHECK_PTR_EQ(drain.multisink_, this);

  const Status peek_status = drain.reader_.PeekFrontWithPreamble(
      buffer, entry_sequence_id_out, bytes_read);

  if (peek_status.IsOutOfRange()) {
    // If the drain has caught up, report the last handled sequence ID so that
    // it can still process any dropped entries.
    entry_sequence_id_out = sequence_id_ - 1;
  } else if (!peek_status.ok()) {
    // Discard the entry if the result isn't OK or OUT_OF_RANGE and exit, as the
    // entry_sequence_id_out cannot be used for computation. Later invocations
    // will calculate the drop count.
    PW_CHECK(drain.reader_.PopFront().ok());
    return peek_status;
  }

  // Compute the drop count delta by comparing this entry's sequence ID with the
  // last sequence ID this drain successfully read.
  //
  // The drop count calculation simply computes the difference between the
  // current and last sequence IDs. Consecutive successful reads will always
  // differ by one at least, so it is subtracted out. If the read was not
  // successful, the difference is not adjusted.
  drop_count_out = entry_sequence_id_out - drain.last_handled_sequence_id_ -
                   (peek_status.ok() ? 1 : 0);

  // The Peek above may have failed due to OutOfRange, now that we've set the
  // drop count see if we should return before attempting to pop.
  if (peek_status.IsOutOfRange()) {
    // No more entries, update the drain.
    drain.last_handled_sequence_id_ = entry_sequence_id_out;
    return peek_status;
  }
  if (request == Request::kPop) {
    PW_CHECK(drain.reader_.PopFront().ok());
    drain.last_handled_sequence_id_ = entry_sequence_id_out;
  }
  return std::as_bytes(buffer.first(bytes_read));
}

void MultiSink::AttachDrain(Drain& drain) {
  std::lock_guard lock(lock_);
  PW_DCHECK_PTR_EQ(drain.multisink_, nullptr);
  drain.multisink_ = this;

  PW_CHECK_OK(ring_buffer_.AttachReader(drain.reader_));
  if (&drain == &oldest_entry_drain_) {
    drain.last_handled_sequence_id_ = sequence_id_ - 1;
  } else {
    drain.last_handled_sequence_id_ =
        oldest_entry_drain_.last_handled_sequence_id_;
  }
  drain.last_peek_sequence_id_ = drain.last_handled_sequence_id_;
}

void MultiSink::DetachDrain(Drain& drain) {
  std::lock_guard lock(lock_);
  PW_DCHECK_PTR_EQ(drain.multisink_, this);
  drain.multisink_ = nullptr;
  PW_CHECK_OK(ring_buffer_.DetachReader(drain.reader_),
              "The drain wasn't already attached.");
}

void MultiSink::AttachListener(Listener& listener) {
  std::lock_guard lock(lock_);
  listeners_.push_back(listener);
  // Notify the newly added entry, in case there are items in the sink.
  listener.OnNewEntryAvailable();
}

void MultiSink::DetachListener(Listener& listener) {
  std::lock_guard lock(lock_);
  [[maybe_unused]] bool was_detached = listeners_.remove(listener);
  PW_DCHECK(was_detached, "The listener was already attached.");
}

void MultiSink::Clear() {
  std::lock_guard lock(lock_);
  ring_buffer_.Clear();
}

void MultiSink::NotifyListeners() {
  for (auto& listener : listeners_) {
    listener.OnNewEntryAvailable();
  }
}

Status MultiSink::UnsafeForEachEntry(
    const Function<void(ConstByteSpan)>& callback, size_t max_num_entries) {
  MultiSink::UnsafeIterationWrapper multisink_iteration = UnsafeIteration();

  // First count the number of entries.
  size_t num_entries = 0;
  for ([[maybe_unused]] ConstByteSpan entry : multisink_iteration) {
    num_entries++;
  }

  // Log up to the max number of logs to avoid overflowing the crash log
  // writer.
  const size_t first_logged_offset =
      max_num_entries > num_entries ? 0 : num_entries - max_num_entries;
  pw::multisink::MultiSink::iterator it = multisink_iteration.begin();
  for (size_t offset = 0; it != multisink_iteration.end(); ++it, ++offset) {
    if (offset < first_logged_offset) {
      continue;  // Skip this log.
    }
    callback(*it);
  }
  if (!it.status().ok()) {
    PW_LOG_WARN("Multisink corruption detected, some entries may be missing");
    return Status::DataLoss();
  }

  return OkStatus();
}

Status MultiSink::Drain::PopEntry(const PeekedEntry& entry) {
  PW_DCHECK_NOTNULL(multisink_);
  return multisink_->PopEntry(*this, entry);
}

Result<MultiSink::Drain::PeekedEntry> MultiSink::Drain::PeekEntry(
    ByteSpan buffer, uint32_t& drop_count_out) {
  PW_DCHECK_NOTNULL(multisink_);
  uint32_t entry_sequence_id_out;
  Result<ConstByteSpan> peek_result = multisink_->PeekOrPopEntry(
      *this, buffer, Request::kPeek, drop_count_out, entry_sequence_id_out);
  if (!peek_result.ok()) {
    return peek_result.status();
  }
  return PeekedEntry(peek_result.value(), entry_sequence_id_out);
}

Result<ConstByteSpan> MultiSink::Drain::PopEntry(ByteSpan buffer,
                                                 uint32_t& drop_count_out) {
  PW_DCHECK_NOTNULL(multisink_);
  uint32_t entry_sequence_id_out;
  return multisink_->PeekOrPopEntry(
      *this, buffer, Request::kPop, drop_count_out, entry_sequence_id_out);
}

}  // namespace multisink
}  // namespace pw
