// 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.data()),
      tokenized_data.size());
  std::string_view expected_data_as_string(
      reinterpret_cast<const char*>(expected_data.data()),
      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
