/* Copyright 2019 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "hardware_verifier/verifier_impl.h"

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>

#include <base/check.h>
#include <base/logging.h>
#include <base/optional.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/system/sys_info.h>
#include <chromeos-config/libcros_config/cros_config.h>

namespace hardware_verifier {

namespace {

constexpr auto kGenericComponentName = "generic";
constexpr auto kNoMatchComponentName = "NO_MATCH";

void AddFoundComponentInfo(
    HwVerificationReport* hw_verification_report,
    const runtime_probe::ProbeRequest_SupportCategory& component_category,
    const std::string& comp_name,
    const QualificationStatus status) {
  auto* found_comp_info = hw_verification_report->add_found_component_infos();
  found_comp_info->set_component_category(component_category);
  found_comp_info->set_component_uuid(comp_name);
  found_comp_info->set_qualification_status(status);
  if (status != QualificationStatus::QUALIFIED) {
    hw_verification_report->set_is_compliant(false);
  }
}

bool IsModelComponent(const ComponentInfo& comp_info,
                      const std::string& model_name) {
  if (model_name.empty())
    return true;

  const auto& parts = base::SplitString(model_name, "_", base::KEEP_WHITESPACE,
                                        base::SPLIT_WANT_ALL);
  return base::StartsWith(comp_info.component_uuid(), parts[0] + "_");
}

}  // namespace

VerifierImpl::VerifierImpl() {
  auto config = std::make_unique<brillo::CrosConfig>();
  CHECK(config->Init());
  cros_config_ = std::move(config);
  using CppType = google::protobuf::FieldDescriptor::CppType;
  constexpr int kCppTypeMsg = CppType::CPPTYPE_MESSAGE;
  constexpr int kCppTypeStr = CppType::CPPTYPE_STRING;

  // Resolve |comp_category_infos_| in the constructor.
  const auto* category_enum_desc =
      runtime_probe::ProbeRequest_SupportCategory_descriptor();
  comp_category_infos_.resize(category_enum_desc->value_count());

  const auto* probe_result_desc = runtime_probe::ProbeResult::descriptor();
  const auto* generic_device_info_desc =
      HwVerificationReport_GenericDeviceInfo::descriptor();
  for (int i = 0; i < category_enum_desc->value_count(); ++i) {
    auto* comp_category_info = &comp_category_infos_[i];
    const auto& comp_category_name = category_enum_desc->value(i)->name();

    comp_category_info->enum_value = category_enum_desc->value(i)->number();
    comp_category_info->enum_name = comp_category_name;

    if (comp_category_info->enum_value ==
        runtime_probe::ProbeRequest_SupportCategory_UNKNOWN)
      continue;

    const auto* field_desc =
        probe_result_desc->FindFieldByName(comp_category_name);
    DCHECK(field_desc && field_desc->cpp_type() == kCppTypeMsg &&
           field_desc->is_repeated())
        << "Field (" << comp_category_name << ") must be a repeated field for "
        << "the HW components in |runtime_probe::ProbeResult|.";
    comp_category_info->probe_result_comp_field = field_desc;

    const auto* probe_result_comp_desc = field_desc->message_type();
    field_desc = probe_result_comp_desc->FindFieldByName("name");
    DCHECK(field_desc && field_desc->cpp_type() == kCppTypeStr &&
           field_desc->is_optional())
        << "Field (" << comp_category_name
        << ") should contain a string of the name of the component.";
    comp_category_info->probe_result_comp_name_field = field_desc;

    field_desc = probe_result_comp_desc->FindFieldByName("values");
    DCHECK(field_desc && field_desc->cpp_type() == kCppTypeMsg &&
           field_desc->is_optional())
        << "Field (" << comp_category_name
        << ") should contain a message field for the component values.";
    comp_category_info->probe_result_comp_values_field = field_desc;

    field_desc = generic_device_info_desc->FindFieldByName(comp_category_name);
    if (field_desc) {
      DCHECK(field_desc->cpp_type() == kCppTypeMsg && field_desc->is_repeated())
          << "|hardware_verifier::HwVerificationReport_GenericDeviceInfo| "
          << "should contain a repeated field for the generic ("
          << comp_category_name << ") components.";
    } else {
      VLOG(1) << "(" << comp_category_name << ") field is not found in "
              << "|hardware_verifier::HwVerificationReport_GenericDeviceInfo|, "
              << "will ignore the generic component of that category.";
    }
    comp_category_info->report_comp_values_field = field_desc;
  }
}

base::Optional<HwVerificationReport> VerifierImpl::Verify(
    const runtime_probe::ProbeResult& probe_result,
    const HwVerificationSpec& hw_verification_spec) const {
  // A dictionary of 'expected_component_category => seen'.
  std::map<int, bool> seen_comp;
  // Collect the categories of generic components we found.
  std::set<int> seen_generic_comp;

  // A dictionary which maps (component_category, component_uuid) to its
  // qualification status.
  std::map<int, std::map<std::string, QualificationStatus>> qual_status_dict;
  const auto model_name = GetModelName();
  for (const auto& comp_info : hw_verification_spec.component_infos()) {
    if (!IsModelComponent(comp_info, model_name))
      continue;
    const auto& category = comp_info.component_category();
    const auto& uuid = comp_info.component_uuid();
    const auto& qualification_status = comp_info.qualification_status();
    const auto& insert_result =
        qual_status_dict[static_cast<int>(category)].emplace(
            uuid, qualification_status);
    if (!insert_result.second) {
      LOG(ERROR)
          << "The verification spec contains duplicated component infos.";
      return base::nullopt;
    }

    // We expect to see this component in probe result.
    seen_comp[category] = false;
  }

  // A dictionary which maps component_category to the field names in the
  // allowlist.
  std::map<int, std::set<std::string>> generic_comp_value_allowlists;
  for (const auto& spec_info :
       hw_verification_spec.generic_component_value_allowlists()) {
    const auto& insert_result = generic_comp_value_allowlists.emplace(
        spec_info.component_category(),
        std::set<std::string>(spec_info.field_names().cbegin(),
                              spec_info.field_names().cend()));
    if (!insert_result.second) {
      LOG(ERROR) << "Duplicated allowlist tables for category (num="
                 << spec_info.component_category() << ") are detected in the "
                 << "verification spec.";
      return base::nullopt;
    }
  }

  HwVerificationReport hw_verification_report;
  hw_verification_report.set_is_compliant(true);
  auto* generic_device_info =
      hw_verification_report.mutable_generic_device_info();
  const auto* generic_device_info_refl = generic_device_info->GetReflection();

  const auto* probe_result_refl = probe_result.GetReflection();
  for (const auto& comp_category_info : comp_category_infos_) {
    if (comp_category_info.enum_value ==
        runtime_probe::ProbeRequest_SupportCategory_UNKNOWN)
      continue;
    const auto& comp_name_to_qual_status =
        qual_status_dict[comp_category_info.enum_value];

    // the default allowlist is empty.
    const auto& generic_comp_value_allowlist =
        generic_comp_value_allowlists[comp_category_info.enum_value];

    const auto& num_comps = probe_result_refl->FieldSize(
        probe_result, comp_category_info.probe_result_comp_field);
    for (int i = 0; i < num_comps; ++i) {
      const auto& comp = probe_result_refl->GetRepeatedMessage(
          probe_result, comp_category_info.probe_result_comp_field, i);
      const auto* comp_refl = comp.GetReflection();
      const auto& comp_name = comp_refl->GetString(
          comp, comp_category_info.probe_result_comp_name_field);

      // If the component name is "generic", add it to |generic_device_info|
      // in the report.
      if (comp_name == kGenericComponentName) {
        seen_generic_comp.insert(comp_category_info.enum_value);
        if (!comp_category_info.report_comp_values_field) {
          VLOG(1) << "Ignore the generic component of ("
                  << comp_category_info.enum_name << ") category.";
        } else {
          // Duplicate the original values and filter the fields by the
          // allowlist.
          auto* dup_comp_values = generic_device_info_refl->AddMessage(
              generic_device_info, comp_category_info.report_comp_values_field);
          dup_comp_values->CopyFrom(comp_refl->GetMessage(
              comp, comp_category_info.probe_result_comp_values_field));

          const auto* dup_comp_values_refl = dup_comp_values->GetReflection();
          const auto* dup_comp_values_desc = dup_comp_values->GetDescriptor();
          for (int j = 0; j < dup_comp_values_desc->field_count(); ++j) {
            const auto* field = dup_comp_values_desc->field(j);
            if (!generic_comp_value_allowlist.count(field->name())) {
              dup_comp_values_refl->ClearField(dup_comp_values, field);
            }
          }
        }
        continue;
      }

      // If the component name is not "generic", do the regular qualification
      // status check.
      const auto& qual_status_it = comp_name_to_qual_status.find(comp_name);
      if (qual_status_it == comp_name_to_qual_status.end()) {
        LOG(ERROR) << "The probe result contains unregonizable components "
                   << "(category=" << comp_category_info.enum_name
                   << ", uuid=" << comp_name << ").";
        return base::nullopt;
      }
      // TODO(b147654337): How about components that are "missing", that is:
      //   - It is expected on the system (according to SKU or MODEL).
      //   - We cannot find this in generic nor non-generic components.
      AddFoundComponentInfo(
          &hw_verification_report,
          static_cast<runtime_probe::ProbeRequest_SupportCategory>(
              comp_category_info.enum_value),
          comp_name, qual_status_it->second);
      seen_comp[comp_category_info.enum_value] = true;
    }
  }

  for (const auto& it : seen_comp) {
    // We have found a generic component in this category, but this doesn't have
    // any qualification status.
    if (!it.second && seen_generic_comp.count(it.first)) {
      AddFoundComponentInfo(
          &hw_verification_report,
          static_cast<runtime_probe::ProbeRequest_SupportCategory>(it.first),
          kNoMatchComponentName, QualificationStatus::NO_MATCH);
    }
  }

  // TODO(yhong): Implement the SKU specific checks.
  return hw_verification_report;
}

void VerifierImpl::SetCrosConfigForTesting(
    std::unique_ptr<brillo::CrosConfigInterface> cros_config) {
  cros_config_ = std::move(cros_config);
}

std::string VerifierImpl::GetModelName() const {
  std::string model_name;

  if (cros_config_ &&
      cros_config_->GetString(kCrosConfigModelNamePath, kCrosConfigModelNameKey,
                              &model_name))
    return model_name;

  // Fallback to sys_info.
  return base::SysInfo::GetLsbReleaseBoard();
}

}  // namespace hardware_verifier
