// Copyright 2022 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_rpc_private/test_utils.h"

#include <cstdint>

#include "gtest/gtest.h"
#include "pw_bytes/span.h"
#include "pw_containers/vector.h"
#include "pw_log/log.h"
#include "pw_log/proto/log.pwpb.h"
#include "pw_log_tokenized/metadata.h"
#include "pw_protobuf/bytes_utils.h"
#include "pw_protobuf/decoder.h"

namespace pw::log_rpc {
namespace {
void VerifyOptionallyTokenizedField(protobuf::Decoder& entry_decoder,
                                    log::LogEntry::Fields field_number,
                                    ConstByteSpan expected_data) {
  if (expected_data.empty()) {
    return;
  }
  ConstByteSpan tokenized_data;
  ASSERT_EQ(entry_decoder.Next(), OkStatus());
  ASSERT_EQ(entry_decoder.FieldNumber(), static_cast<uint32_t>(field_number));
  ASSERT_EQ(entry_decoder.ReadBytes(&tokenized_data), OkStatus());
  std::string_view data_as_string(
      reinterpret_cast<const char*>(tokenized_data.begin()),
      tokenized_data.size());
  std::string_view expected_data_as_string(
      reinterpret_cast<const char*>(expected_data.begin()),
      expected_data.size());
  EXPECT_EQ(data_as_string, expected_data_as_string);
}
}  // namespace

// Unpacks a `LogEntry` proto buffer to compare it with the expected data and
// updates the total drop count found.
void VerifyLogEntry(protobuf::Decoder& entry_decoder,
                    const TestLogEntry& expected_entry,
                    uint32_t& drop_count_out) {
  VerifyOptionallyTokenizedField(entry_decoder,
                                 log::LogEntry::Fields::MESSAGE,
                                 expected_entry.tokenized_data);
  if (expected_entry.metadata.level()) {
    ASSERT_EQ(entry_decoder.Next(), OkStatus());
    ASSERT_EQ(entry_decoder.FieldNumber(),
              static_cast<uint32_t>(log::LogEntry::Fields::LINE_LEVEL));
    uint32_t line_level;
    ASSERT_TRUE(entry_decoder.ReadUint32(&line_level).ok());
    EXPECT_EQ(expected_entry.metadata.level(),
              line_level & PW_LOG_LEVEL_BITMASK);
    EXPECT_EQ(expected_entry.metadata.line_number(),
              (line_level & ~PW_LOG_LEVEL_BITMASK) >> PW_LOG_LEVEL_BITS);
  }
  if (expected_entry.metadata.flags()) {
    ASSERT_EQ(entry_decoder.Next(), OkStatus());
    ASSERT_EQ(entry_decoder.FieldNumber(),
              static_cast<uint32_t>(log::LogEntry::Fields::FLAGS));
    uint32_t flags;
    ASSERT_TRUE(entry_decoder.ReadUint32(&flags).ok());
    EXPECT_EQ(expected_entry.metadata.flags(), flags);
  }
  if (expected_entry.timestamp) {
    ASSERT_EQ(entry_decoder.Next(), OkStatus());
    ASSERT_TRUE(entry_decoder.FieldNumber() ==
                    static_cast<uint32_t>(log::LogEntry::Fields::TIMESTAMP) ||
                entry_decoder.FieldNumber() ==
                    static_cast<uint32_t>(
                        log::LogEntry::Fields::TIME_SINCE_LAST_ENTRY));
    int64_t timestamp;
    ASSERT_TRUE(entry_decoder.ReadInt64(&timestamp).ok());
    EXPECT_EQ(expected_entry.timestamp, timestamp);
  }
  if (expected_entry.dropped) {
    ASSERT_EQ(entry_decoder.Next(), OkStatus());
    ASSERT_EQ(entry_decoder.FieldNumber(),
              static_cast<uint32_t>(log::LogEntry::Fields::DROPPED));
    uint32_t dropped = 0;
    ASSERT_TRUE(entry_decoder.ReadUint32(&dropped).ok());
    EXPECT_EQ(expected_entry.dropped, dropped);
    drop_count_out += dropped;
  }
  if (expected_entry.metadata.module()) {
    ASSERT_EQ(entry_decoder.Next(), OkStatus());
    ASSERT_EQ(entry_decoder.FieldNumber(),
              static_cast<uint32_t>(log::LogEntry::Fields::MODULE));
    const Result<uint32_t> module =
        protobuf::DecodeBytesToUint32(entry_decoder);
    ASSERT_EQ(module.status(), OkStatus());
    EXPECT_EQ(expected_entry.metadata.module(), module.value());
  }
  VerifyOptionallyTokenizedField(
      entry_decoder, log::LogEntry::Fields::FILE, expected_entry.file);
  VerifyOptionallyTokenizedField(
      entry_decoder, log::LogEntry::Fields::THREAD, expected_entry.thread);
}

// Compares an encoded LogEntry's fields against the expected sequence ID and
// LogEntries, and updates the total entry and drop counts. Starts comparing at
// `expected_entries[entries_count_out]`. `expected_entries` must be in the same
// order that messages were added to the MultiSink.
void VerifyLogEntries(protobuf::Decoder& entries_decoder,
                      const Vector<TestLogEntry>& expected_entries,
                      uint32_t expected_first_entry_sequence_id,
                      size_t& entries_count_out,
                      uint32_t& drop_count_out) {
  size_t entry_index = entries_count_out;
  while (entries_decoder.Next().ok()) {
    if (static_cast<pw::log::LogEntries::Fields>(
            entries_decoder.FieldNumber()) ==
        log::LogEntries::Fields::ENTRIES) {
      ConstByteSpan entry;
      EXPECT_EQ(entries_decoder.ReadBytes(&entry), OkStatus());
      protobuf::Decoder entry_decoder(entry);
      if (expected_entries.empty()) {
        break;
      }

      ASSERT_LT(entry_index, expected_entries.size());

      // Keep track of entries and drops respective counts.
      uint32_t current_drop_count = 0;
      VerifyLogEntry(
          entry_decoder, expected_entries[entry_index], current_drop_count);
      ++entry_index;
      drop_count_out += current_drop_count;
      if (current_drop_count == 0) {
        ++entries_count_out;
      }
    } else if (static_cast<pw::log::LogEntries::Fields>(
                   entries_decoder.FieldNumber()) ==
               log::LogEntries::Fields::FIRST_ENTRY_SEQUENCE_ID) {
      uint32_t first_entry_sequence_id = 0;
      EXPECT_EQ(entries_decoder.ReadUint32(&first_entry_sequence_id),
                OkStatus());
      EXPECT_EQ(expected_first_entry_sequence_id, first_entry_sequence_id);
    }
  }
}

size_t CountLogEntries(protobuf::Decoder& entries_decoder) {
  size_t entries_found = 0;
  while (entries_decoder.Next().ok()) {
    if (static_cast<pw::log::LogEntries::Fields>(
            entries_decoder.FieldNumber()) ==
        log::LogEntries::Fields::ENTRIES) {
      ++entries_found;
    }
  }
  return entries_found;
}

}  // namespace pw::log_rpc
