// 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, 128)
  context(filter_map_);
  context.call({});
  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, 128)
  no_filter_context(empty_filter_map);
  no_filter_context.call({});
  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, 128)
  context(filter_map_);
  context.call(request.value());

  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, 128)
  context(filter_map_);
  context.call(request.value());

  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, 128)
  context_no_filter(filter_map_);
  context_no_filter.call({});
  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, 128)
  context_new_filter(filter_map_);
  context_new_filter.call(second_filter_request.value());

  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, 128)
  context(filter_map_);

  std::byte request_buffer[64];
  log::GetFilterRequest::MemoryEncoder encoder(request_buffer);
  encoder.WriteFilterId(filter_id1_);
  const auto request = ConstByteSpan(encoder);
  context.call(request);
  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, 128)
  context2(filter_map_);
  context2.call(request);
  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, 128)
  context3(filter_map_);
  context3.call(request);
  ASSERT_EQ(context3.responses().size(), 1u);
  protobuf::Decoder decoder3(context3.responses()[0]);
  VerifyFilterRules(decoder3, rules1_);
}

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