// 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_log_rpc/log_filter_service.h"

#include <array>
#include <cstdint>
#include <limits>

#include "gtest/gtest.h"
#include "pw_bytes/endian.h"
#include "pw_log/proto/log.pwpb.h"
#include "pw_log_rpc/log_filter.h"
#include "pw_log_rpc/log_filter_map.h"
#include "pw_protobuf/bytes_utils.h"
#include "pw_protobuf/decoder.h"
#include "pw_result/result.h"
#include "pw_rpc/channel.h"
#include "pw_rpc/raw/test_method_context.h"

namespace pw::log_rpc {
namespace {

class FilterServiceTest : public ::testing::Test {
 public:
  FilterServiceTest() : filter_map_(filters_) {}

 protected:
  FilterMap filter_map_;
  static constexpr size_t kMaxFilterRules = 3;
  std::array<Filter::Rule, kMaxFilterRules> rules1_;
  std::array<Filter::Rule, kMaxFilterRules> rules2_;
  std::array<Filter::Rule, kMaxFilterRules> rules3_;
  static constexpr std::array<std::byte, cfg::kMaxFilterIdBytes> filter_id1_{
      std::byte(65), std::byte(66), std::byte(67), std::byte(0)};
  static constexpr std::array<std::byte, cfg::kMaxFilterIdBytes> filter_id2_{
      std::byte(68), std::byte(69), std::byte(70), std::byte(0)};
  static constexpr std::array<std::byte, cfg::kMaxFilterIdBytes> filter_id3_{
      std::byte(71), std::byte(72), std::byte(73), std::byte(0)};
  static constexpr size_t kMaxFilters = 3;
  std::array<Filter, kMaxFilters> filters_ = {
      Filter(filter_id1_, rules1_),
      Filter(filter_id2_, rules2_),
      Filter(filter_id3_, rules3_),
  };
};

TEST_F(FilterServiceTest, GetFilterIds) {
  PW_RAW_TEST_METHOD_CONTEXT(FilterService, ListFilterIds, 1)
  context(filter_map_);
  context.call({});
  ASSERT_EQ(OkStatus(), context.status());
  ASSERT_TRUE(context.done());
  ASSERT_EQ(context.responses().size(), 1u);
  protobuf::Decoder decoder(context.responses()[0]);

  for (const auto& filter : filter_map_.filters()) {
    ASSERT_EQ(decoder.Next(), OkStatus());
    ASSERT_EQ(decoder.FieldNumber(), 1u);  // filter_id
    ConstByteSpan filter_id;
    ASSERT_EQ(decoder.ReadBytes(&filter_id), OkStatus());
    ASSERT_EQ(filter_id.size(), filter.id().size());
    EXPECT_EQ(
        std::memcmp(filter_id.data(), filter.id().data(), filter_id.size()), 0);
  }
  EXPECT_FALSE(decoder.Next().ok());

  // No IDs reported when the filter map is empty.
  FilterMap empty_filter_map({});
  PW_RAW_TEST_METHOD_CONTEXT(FilterService, ListFilterIds, 1)
  no_filter_context(empty_filter_map);
  no_filter_context.call({});
  ASSERT_EQ(OkStatus(), no_filter_context.status());
  ASSERT_TRUE(no_filter_context.done());
  ASSERT_EQ(no_filter_context.responses().size(), 1u);
  protobuf::Decoder no_filter_decoder(no_filter_context.responses()[0]);
  uint32_t filter_count = 0;
  while (no_filter_decoder.Next().ok()) {
    EXPECT_EQ(no_filter_decoder.FieldNumber(), 1u);  // filter_id
    ++filter_count;
  }
  EXPECT_EQ(filter_count, 0u);
}

Status EncodeFilterRule(const Filter::Rule& rule,
                        log::FilterRule::StreamEncoder& encoder) {
  PW_TRY(
      encoder.WriteLevelGreaterThanOrEqual(rule.level_greater_than_or_equal));
  PW_TRY(encoder.WriteModuleEquals(rule.module_equals));
  PW_TRY(encoder.WriteAnyFlagsSet(rule.any_flags_set));
  return encoder.WriteAction(static_cast<log::FilterRule::Action>(rule.action));
}

Status EncodeFilter(const Filter& filter, log::Filter::StreamEncoder& encoder) {
  for (auto& rule : filter.rules()) {
    log::FilterRule::StreamEncoder rule_encoder = encoder.GetRuleEncoder();
    PW_TRY(EncodeFilterRule(rule, rule_encoder));
  }
  return OkStatus();
}

Result<ConstByteSpan> EncodeFilterRequest(const Filter& filter,
                                          ByteSpan buffer) {
  stream::MemoryWriter writer(buffer);
  std::byte encode_buffer[256];
  protobuf::StreamEncoder encoder(writer, encode_buffer);
  PW_TRY(encoder.WriteBytes(
      static_cast<uint32_t>(log::SetFilterRequest::Fields::FILTER_ID),
      filter.id()));
  {
    log::Filter::StreamEncoder filter_encoder = encoder.GetNestedEncoder(
        static_cast<uint32_t>(log::SetFilterRequest::Fields::FILTER));
    PW_TRY(EncodeFilter(filter, filter_encoder));
  }  // Let the StreamEncoder destructor finalize the data.
  return ConstByteSpan(writer.data(), writer.bytes_written());
}

void VerifyRule(const Filter::Rule& rule, const Filter::Rule& expected_rule) {
  EXPECT_EQ(rule.level_greater_than_or_equal,
            expected_rule.level_greater_than_or_equal);
  EXPECT_EQ(rule.module_equals, expected_rule.module_equals);
  EXPECT_EQ(rule.any_flags_set, expected_rule.any_flags_set);
  EXPECT_EQ(rule.action, expected_rule.action);
}

TEST_F(FilterServiceTest, SetFilterRules) {
  const std::array<Filter::Rule, 4> new_rules{{
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::DEBUG_LEVEL,
          .any_flags_set = 0x0f,
          .module_equals{std::byte(123)},
      },
      {
          .action = Filter::Rule::Action::kInactive,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0xef,
          .module_equals{},
      },
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::INFO_LEVEL,
          .any_flags_set = 0x1234,
          .module_equals{std::byte(99)},
      },
      {
          .action = Filter::Rule::Action::kDrop,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0,
          .module_equals{std::byte(4)},
      },
  }};
  const Filter new_filter(filters_[0].id(),
                          const_cast<std::array<Filter::Rule, 4>&>(new_rules));

  std::byte request_buffer[512];
  const auto request = EncodeFilterRequest(new_filter, request_buffer);
  ASSERT_EQ(request.status(), OkStatus());

  PW_RAW_TEST_METHOD_CONTEXT(FilterService, SetFilter, 1)
  context(filter_map_);
  context.call(request.value());
  ASSERT_EQ(OkStatus(), context.status());

  size_t i = 0;
  for (const auto& rule : filters_[0].rules()) {
    VerifyRule(rule, new_rules[i++]);
  }
}

TEST_F(FilterServiceTest, SetFilterRulesWhenUsedByDrain) {
  const std::array<Filter::Rule, 4> new_filter_rules{{
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::CRITICAL_LEVEL,
          .any_flags_set = 0xfd,
          .module_equals{std::byte(543)},
      },
      {
          .action = Filter::Rule::Action::kInactive,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0xca,
          .module_equals{},
      },
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::INFO_LEVEL,
          .any_flags_set = 0xabcd,
          .module_equals{std::byte(9000)},
      },
      {
          .action = Filter::Rule::Action::kDrop,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0,
          .module_equals{std::byte(123)},
      },
  }};
  Filter& filter = filters_[0];
  const Filter new_filter(
      filter.id(), const_cast<std::array<Filter::Rule, 4>&>(new_filter_rules));

  std::byte request_buffer[256];
  const auto request = EncodeFilterRequest(new_filter, request_buffer);
  ASSERT_EQ(request.status(), OkStatus());

  PW_RAW_TEST_METHOD_CONTEXT(FilterService, SetFilter, 1)
  context(filter_map_);
  context.call(request.value());
  ASSERT_EQ(OkStatus(), context.status());

  size_t i = 0;
  for (const auto& rule : filter.rules()) {
    VerifyRule(rule, new_filter_rules[i++]);
  }

  // An empty request should not modify the filter.
  PW_RAW_TEST_METHOD_CONTEXT(FilterService, SetFilter, 1)
  context_no_filter(filter_map_);
  context_no_filter.call({});
  EXPECT_EQ(Status::OutOfRange(), context_no_filter.status());

  i = 0;
  for (const auto& rule : filter.rules()) {
    VerifyRule(rule, new_filter_rules[i++]);
  }

  // A new request for logs with a new filter updates filter.
  const std::array<Filter::Rule, 4> second_filter_rules{{
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::DEBUG_LEVEL,
          .any_flags_set = 0xab,
          .module_equals{},
      },
      {
          .action = Filter::Rule::Action::kDrop,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0x11,
          .module_equals{std::byte(34)},
      },
      {
          .action = Filter::Rule::Action::kKeep,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0xef,
          .module_equals{std::byte(23)},
      },
      {
          .action = Filter::Rule::Action::kDrop,
          .level_greater_than_or_equal = log::FilterRule::Level::ANY_LEVEL,
          .any_flags_set = 0x0f,
          .module_equals{},
      },
  }};
  const Filter second_filter(
      filter.id(),
      const_cast<std::array<Filter::Rule, 4>&>(second_filter_rules));

  std::memset(request_buffer, 0, sizeof(request_buffer));
  const auto second_filter_request =
      EncodeFilterRequest(second_filter, request_buffer);
  ASSERT_EQ(second_filter_request.status(), OkStatus());
  PW_RAW_TEST_METHOD_CONTEXT(FilterService, SetFilter, 1)
  context_new_filter(filter_map_);
  context_new_filter.call(second_filter_request.value());
  ASSERT_EQ(OkStatus(), context.status());

  i = 0;
  for (const auto& rule : filter.rules()) {
    VerifyRule(rule, second_filter_rules[i++]);
  }
}

void VerifyFilterRule(protobuf::Decoder& decoder,
                      const Filter::Rule& expected_rule) {
  ASSERT_TRUE(decoder.Next().ok());
  ASSERT_EQ(decoder.FieldNumber(), 1u);  // level_greater_than_or_equal
  log::FilterRule::Level level_greater_than_or_equal;
  ASSERT_EQ(decoder.ReadUint32(
                reinterpret_cast<uint32_t*>(&level_greater_than_or_equal)),
            OkStatus());
  EXPECT_EQ(level_greater_than_or_equal,
            expected_rule.level_greater_than_or_equal);

  ASSERT_TRUE(decoder.Next().ok());
  ASSERT_EQ(decoder.FieldNumber(), 2u);  // module_equals
  ConstByteSpan module_equals;
  ASSERT_EQ(decoder.ReadBytes(&module_equals), OkStatus());
  ASSERT_EQ(module_equals.size(), expected_rule.module_equals.size());
  EXPECT_EQ(std::memcmp(module_equals.data(),
                        expected_rule.module_equals.data(),
                        module_equals.size()),
            0);

  ASSERT_TRUE(decoder.Next().ok());
  ASSERT_EQ(decoder.FieldNumber(), 3u);  // any_flags_set
  uint32_t any_flags_set;
  ASSERT_EQ(decoder.ReadUint32(&any_flags_set), OkStatus());
  EXPECT_EQ(any_flags_set, expected_rule.any_flags_set);

  ASSERT_TRUE(decoder.Next().ok());
  ASSERT_EQ(decoder.FieldNumber(), 4u);  // action
  Filter::Rule::Action action;
  ASSERT_EQ(decoder.ReadUint32(reinterpret_cast<uint32_t*>(&action)),
            OkStatus());
  EXPECT_EQ(action, expected_rule.action);
}

void VerifyFilterRules(protobuf::Decoder& decoder,
                       std::span<const Filter::Rule> expected_rules) {
  size_t rules_found = 0;
  while (decoder.Next().ok()) {
    ConstByteSpan rule;
    EXPECT_TRUE(decoder.ReadBytes(&rule).ok());
    protobuf::Decoder rule_decoder(rule);
    if (rules_found >= expected_rules.size()) {
      break;
    }
    VerifyFilterRule(rule_decoder, expected_rules[rules_found]);
    ++rules_found;
  }
  EXPECT_EQ(rules_found, expected_rules.size());
}

TEST_F(FilterServiceTest, GetFilterRules) {
  PW_RAW_TEST_METHOD_CONTEXT(FilterService, GetFilter, 1)
  context(filter_map_);

  std::byte request_buffer[64];
  log::GetFilterRequest::MemoryEncoder encoder(request_buffer);
  ASSERT_EQ(OkStatus(), encoder.WriteFilterId(filter_id1_));
  const auto request = ConstByteSpan(encoder);
  context.call(request);
  ASSERT_EQ(OkStatus(), context.status());
  ASSERT_TRUE(context.done());
  ASSERT_EQ(context.responses().size(), 1u);

  // Verify against empty rules.
  protobuf::Decoder decoder(context.responses()[0]);
  VerifyFilterRules(decoder, rules1_);

  // Partially populate rules.
  rules1_[0].action = Filter::Rule::Action::kKeep;
  rules1_[0].level_greater_than_or_equal = log::FilterRule::Level::DEBUG_LEVEL;
  rules1_[0].any_flags_set = 0xab;
  const std::array<std::byte, 2> module1{std::byte(123), std::byte(0xab)};
  rules1_[0].module_equals.assign(module1.begin(), module1.end());
  rules1_[1].action = Filter::Rule::Action::kDrop;
  rules1_[1].level_greater_than_or_equal = log::FilterRule::Level::ERROR_LEVEL;
  rules1_[1].any_flags_set = 0;

  PW_RAW_TEST_METHOD_CONTEXT(FilterService, GetFilter, 1)
  context2(filter_map_);
  context2.call(request);
  ASSERT_EQ(OkStatus(), context2.status());
  ASSERT_EQ(context2.responses().size(), 1u);
  protobuf::Decoder decoder2(context2.responses()[0]);
  VerifyFilterRules(decoder2, rules1_);

  // Modify the rest of the filter rules.
  rules1_[2].action = Filter::Rule::Action::kKeep;
  rules1_[2].level_greater_than_or_equal = log::FilterRule::Level::FATAL_LEVEL;
  rules1_[2].any_flags_set = 0xcd;
  const std::array<std::byte, 2> module2{std::byte(1), std::byte(2)};
  rules1_[2].module_equals.assign(module2.begin(), module2.end());
  rules1_[3].action = Filter::Rule::Action::kInactive;

  PW_RAW_TEST_METHOD_CONTEXT(FilterService, GetFilter, 1)
  context3(filter_map_);
  context3.call(request);
  ASSERT_EQ(OkStatus(), context3.status());
  ASSERT_EQ(context3.responses().size(), 1u);
  protobuf::Decoder decoder3(context3.responses()[0]);
  VerifyFilterRules(decoder3, rules1_);
}

}  // namespace
}  // namespace pw::log_rpc
