// 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_log_multisink/log_queue.h"

#include "pw_assert/check.h"
#include "pw_log/levels.h"
#include "pw_log/proto/log.pwpb.h"
#include "pw_protobuf/wire_format.h"
#include "pw_status/try.h"

namespace pw::log_rpc {
namespace {

using pw::protobuf::WireType;
constexpr uint32_t kLogKey = pw::protobuf::MakeKey(
    static_cast<uint32_t>(pw::log::LogEntries::Fields::ENTRIES),
    WireType::kDelimited);

}  // namespace

Status LogQueue::PushTokenizedMessage(ConstByteSpan message,
                                      uint32_t flags,
                                      uint32_t level,
                                      uint32_t line,
                                      uint32_t thread,
                                      int64_t timestamp) {
  pw::protobuf::NestedEncoder nested_encoder(encode_buffer_);
  pw::log::LogEntry::Encoder encoder(&nested_encoder);
  Status status;

  encoder.WriteMessageTokenized(message);
  encoder.WriteLineLevel((level & PW_LOG_LEVEL_BITMASK) |
                         ((line << PW_LOG_LEVEL_BITS) & ~PW_LOG_LEVEL_BITMASK));
  encoder.WriteFlags(flags);
  encoder.WriteThreadTokenized(thread);

  // TODO(prashanthsw): Add support for delta encoding of the timestamp.
  encoder.WriteTimestamp(timestamp);

  if (dropped_entries_ > 0) {
    encoder.WriteDropped(dropped_entries_);
  }

  ConstByteSpan log_entry;
  status = nested_encoder.Encode(&log_entry);
  if (!status.ok() || log_entry.size_bytes() > max_log_entry_size_) {
    // If an encoding failure occurs or the constructed log entry is larger
    // than the configured max size, map the error to INTERNAL. If the
    // underlying allocation of this encode buffer or the nested encoding
    // sequencing are at fault, they are not the caller's responsibility. If
    // the log entry is larger than the max allowed size, the log is dropped
    // intentionally, and it is expected that the caller accepts this
    // possibility.
    status = PW_STATUS_INTERNAL;
  } else {
    // Try to push back the encoded log entry.
    status = ring_buffer_.TryPushBack(log_entry, kLogKey);
  }

  if (!status.ok()) {
    // The ring buffer may hit the RESOURCE_EXHAUSTED state, causing us
    // to drop packets. However, this check captures all failures from
    // Encode and TryPushBack, as any failure here causes packet drop.
    dropped_entries_++;
    latest_dropped_timestamp_ = timestamp;
    return status;
  }

  dropped_entries_ = 0;
  return OkStatus();
}

Result<LogEntries> LogQueue::Pop(LogEntriesBuffer entry_buffer) {
  size_t ring_buffer_entry_size = 0;
  PW_TRY(pop_status_for_test_);
  // The caller must provide a buffer that is at minimum max_log_entry_size, to
  // ensure that the front entry of the ring buffer can be popped.
  PW_DCHECK_UINT_GE(entry_buffer.size_bytes(), max_log_entry_size_);
  PW_TRY(ring_buffer_.PeekFrontWithPreamble(entry_buffer,
                                            &ring_buffer_entry_size));
  PW_DCHECK_OK(ring_buffer_.PopFront());

  return LogEntries{
      .entries = ConstByteSpan(entry_buffer.first(ring_buffer_entry_size)),
      .entry_count = 1};
}

LogEntries LogQueue::PopMultiple(LogEntriesBuffer entries_buffer) {
  size_t offset = 0;
  size_t entry_count = 0;

  // The caller must provide a buffer that is at minimum max_log_entry_size, to
  // ensure that the front entry of the ring buffer can be popped.
  PW_DCHECK_UINT_GE(entries_buffer.size_bytes(), max_log_entry_size_);

  while (ring_buffer_.EntryCount() > 0 &&
         (entries_buffer.size_bytes() - offset) > max_log_entry_size_) {
    const Result<LogEntries> result = Pop(entries_buffer.subspan(offset));
    if (!result.ok()) {
      break;
    }
    offset += result.value().entries.size_bytes();
    entry_count += result.value().entry_count;
  }

  return LogEntries{.entries = ConstByteSpan(entries_buffer.first(offset)),
                    .entry_count = entry_count};
}

}  // namespace pw::log_rpc
