// 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_rpc/log_filter.h"

#include "pw_log/levels.h"
#include "pw_protobuf/decoder.h"
#include "pw_status/try.h"

namespace pw::log_rpc {
namespace {

// Returns true if the provided log parameters match the given filter rule.
bool IsRuleMet(const Filter::Rule& rule,
               uint32_t level,
               ConstByteSpan module,
               uint32_t flags) {
  if (level < static_cast<uint32_t>(rule.level_greater_than_or_equal)) {
    return false;
  }
  if ((rule.any_flags_set != 0) && ((flags & rule.any_flags_set) == 0)) {
    return false;
  }
  if (!rule.module_equals.empty() && !std::equal(module.begin(),
                                                 module.end(),
                                                 rule.module_equals.begin(),
                                                 rule.module_equals.end())) {
    return false;
  }
  return true;
}

}  // namespace

Status Filter::UpdateRulesFromProto(ConstByteSpan buffer) {
  if (rules_.empty()) {
    return Status::FailedPrecondition();
  }

  // Reset rules.
  for (auto& rule : rules_) {
    rule = {};
  }

  protobuf::Decoder decoder(buffer);
  Status status;
  for (size_t i = 0; (i < rules_.size()) && (status = decoder.Next()).ok();
       ++i) {
    ConstByteSpan rule_buffer;
    PW_TRY(decoder.ReadBytes(&rule_buffer));
    protobuf::Decoder rule_decoder(rule_buffer);
    while ((status = rule_decoder.Next()).ok()) {
      switch (
          static_cast<log::FilterRule::Fields>(rule_decoder.FieldNumber())) {
        case log::FilterRule::Fields::LEVEL_GREATER_THAN_OR_EQUAL:
          PW_TRY(rule_decoder.ReadUint32(reinterpret_cast<uint32_t*>(
              &rules_[i].level_greater_than_or_equal)));
          break;
        case log::FilterRule::Fields::MODULE_EQUALS: {
          ConstByteSpan module;
          PW_TRY(rule_decoder.ReadBytes(&module));
          if (module.size() > rules_[i].module_equals.max_size()) {
            return Status::InvalidArgument();
          }
          rules_[i].module_equals.assign(module.begin(), module.end());
        } break;
        case log::FilterRule::Fields::ANY_FLAGS_SET:
          PW_TRY(rule_decoder.ReadUint32(&rules_[i].any_flags_set));
          break;
        case log::FilterRule::Fields::ACTION:
          PW_TRY(rule_decoder.ReadUint32(
              reinterpret_cast<uint32_t*>(&rules_[i].action)));
          break;
      }
    }
  }
  return status.IsOutOfRange() ? OkStatus() : status;
}

bool Filter::ShouldDropLog(ConstByteSpan entry) const {
  if (rules_.empty()) {
    return false;
  }

  uint32_t log_level = 0;
  ConstByteSpan log_module;
  uint32_t log_flags = 0;
  protobuf::Decoder decoder(entry);
  while (decoder.Next().ok()) {
    switch (static_cast<log::LogEntry::Fields>(decoder.FieldNumber())) {
      case log::LogEntry::Fields::LINE_LEVEL:
        if (decoder.ReadUint32(&log_level).ok()) {
          log_level &= PW_LOG_LEVEL_BITMASK;
        }
        break;
      case log::LogEntry::Fields::MODULE:
        decoder.ReadBytes(&log_module).IgnoreError();
        break;
      case log::LogEntry::Fields::FLAGS:
        decoder.ReadUint32(&log_flags).IgnoreError();
        break;
      default:
        break;
    }
  }

  // Follow the action of the first rule whose condition is met.
  for (const auto& rule : rules_) {
    if (rule.action == Filter::Rule::Action::kInactive) {
      continue;
    }
    if (IsRuleMet(rule, log_level, log_module, log_flags)) {
      return rule.action == Filter::Rule::Action::kDrop;
    }
  }

  return false;
}

}  // namespace pw::log_rpc
