/* 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>
#include <runtime_probe/proto_bindings/runtime_probe.pb.h>

namespace hardware_verifier {

namespace {

using CppType = google::protobuf::FieldDescriptor::CppType;
using SupportCategory = runtime_probe::ProbeRequest_SupportCategory;

constexpr int kCppTypeMsg = CppType::CPPTYPE_MESSAGE;
constexpr int kCppTypeStr = CppType::CPPTYPE_STRING;

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

void FilterComponentFields(google::protobuf::Message* comp_values,
                           const std::set<std::string>& comp_value_allowlist) {
  const auto* comp_values_refl = comp_values->GetReflection();
  const auto* comp_values_desc = comp_values->GetDescriptor();
  for (int j = 0; j < comp_values_desc->field_count(); ++j) {
    const auto* field = comp_values_desc->field(j);
    if (!comp_value_allowlist.count(field->name())) {
      comp_values_refl->ClearField(comp_values, field);
    }
  }
}

void SetComponentFields(ComponentInfo* component_info,
                        SupportCategory category,
                        const google::protobuf::Message& values) {
  auto comp_fields = component_info->mutable_component_fields();
  auto comp_fields_desc = comp_fields->GetDescriptor();
  auto comp_fields_refl = comp_fields->GetReflection();
  auto category_name =
      runtime_probe::ProbeRequest_SupportCategory_Name(category);
  auto* fields_desc = comp_fields_desc->FindFieldByName(category_name);
  DCHECK(fields_desc && fields_desc->cpp_type() == kCppTypeMsg &&
         fields_desc->is_optional());
  auto* fields = comp_fields_refl->MutableMessage(comp_fields, fields_desc);
  fields->CopyFrom(values);
}

void AddFoundComponentInfo(HwVerificationReport* hw_verification_report,
                           SupportCategory component_category,
                           const std::string& comp_name,
                           google::protobuf::Message* comp_values,
                           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 (comp_values) {
    SetComponentFields(found_comp_info, component_category, *comp_values);
  }
  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);
  // 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 =
        static_cast<SupportCategory>(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<SupportCategory, bool> seen_comp;
  // Collect the categories of generic components we found.
  std::set<SupportCategory> seen_generic_comp;

  // A dictionary which maps (component_category, component_uuid) to its
  // qualification status.
  std::map<SupportCategory, 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[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<SupportCategory, 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);
      const auto& comp_values = comp_refl->GetMessage(
          comp, comp_category_info.probe_result_comp_values_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* generic_comp_values = generic_device_info_refl->AddMessage(
              generic_device_info, comp_category_info.report_comp_values_field);
          generic_comp_values->CopyFrom(comp_values);
          FilterComponentFields(generic_comp_values,
                                generic_comp_value_allowlist);
        }
        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.
      auto* filtered_comp_values = comp_values.New();
      filtered_comp_values->CopyFrom(comp_values);
      FilterComponentFields(filtered_comp_values, generic_comp_value_allowlist);
      AddFoundComponentInfo(&hw_verification_report,
                            comp_category_info.enum_value, comp_name,
                            filtered_comp_values, qual_status_it->second);
      seen_comp[comp_category_info.enum_value] = true;
      delete filtered_comp_values;
    }
  }

  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, it.first,
                            kNoMatchComponentName, nullptr,
                            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
