/* Copyright 2020 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 <memory>
#include <string>
#include <utility>

#include <base/check.h>
#include <base/logging.h>
#include <base/no_destructor.h>
#include <base/strings/strcat.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <metrics/metrics_library.h>
#include <metrics/structured/structured_events.h>

#include <runtime_probe/proto_bindings/runtime_probe.pb.h>

#include "hardware_verifier/hardware_verifier.pb.h"
#include "hardware_verifier/observer.h"

namespace hardware_verifier {

namespace {

using StructuredComponentInfo =
    metrics::structured::events::hardware_verifier::ComponentInfo;
using StructuredHwVerificationReport =
    metrics::structured::events::hardware_verifier::HwVerificationReport;

StructuredComponentInfo CreateStructuredComponentInfo(
    const runtime_probe::Edid::Fields& device) {
  runtime_probe::Edid::Vendor vendor = runtime_probe::Edid::VENDOR_UNKNOWN;
  if (!runtime_probe::Edid::Vendor_Parse(
          base::StringPrintf("VENDOR_%s", device.vendor().c_str()), &vendor)) {
    VLOG(3) << "Unknown EDID vendor : " << device.vendor();
  }
  return StructuredComponentInfo()
      .SetComponentCategory(
          runtime_probe::ProbeRequest_SupportCategory_display_panel)
      .SetDisplayPanelVendor(vendor)
      .SetDisplayPanelProductId(device.product_id())
      .SetDisplayPanelHeight(device.height())
      .SetDisplayPanelWidth(device.width());
}

StructuredComponentInfo CreateStructuredComponentInfo(
    const runtime_probe::Storage::Fields& device) {
  auto info = StructuredComponentInfo();
  if (device.type() == "MMC") {
    info.SetComponentCategory(
            runtime_probe::ProbeRequest_SupportCategory_storage)
        .SetStorageMmcManfid(device.mmc_manfid())
        .SetStorageMmcHwrev(device.mmc_hwrev())
        .SetStorageMmcOemid(device.mmc_oemid())
        .SetStorageMmcPrv(device.mmc_prv());
  } else if (device.type() == "NVMe") {
    info.SetComponentCategory(
            runtime_probe::ProbeRequest_SupportCategory_storage)
        .SetStoragePciVendor(device.pci_vendor())
        .SetStoragePciDevice(device.pci_device())
        .SetStoragePciClass(device.pci_class());
  } else if (device.type() == "ATA") {
    // Do nothing since all fields for ATA are string type.
  }
  return info;
}

void RecordStructuredHwVerificationReport(const HwVerificationReport& report) {
  auto report_event = StructuredHwVerificationReport();
  report_event.SetIsCompliant(report.is_compliant());
  for (auto i = 0; i < report.found_component_infos_size(); i++) {
    const auto& info = report.found_component_infos(i);
    const auto& qualification_status = info.qualification_status();
    switch (info.component_category()) {
      case runtime_probe::ProbeRequest_SupportCategory_display_panel:
        report_event.SetQualificationStatusDisplayPanel(qualification_status);
        break;
      case runtime_probe::ProbeRequest_SupportCategory_storage:
        report_event.SetQualificationStatusStorage(qualification_status);
        break;
      default:
        break;
    }
  }
  report_event.Record();

  for (const auto& device : report.generic_device_info().display_panel()) {
    CreateStructuredComponentInfo(device).Record();
  }
  for (const auto& device : report.generic_device_info().storage()) {
    auto event = CreateStructuredComponentInfo(device);
    if (!event.metrics().empty())
      event.Record();
  }
}

}  // namespace

Observer* Observer::GetInstance() {
  static base::NoDestructor<Observer> instance;
  return instance.get();
}

void Observer::StartTimer(const std::string& timer_name) {
  VLOG(1) << "Start timer |" << timer_name << "|";
  timers_[timer_name] = base::TimeTicks::Now();
}

void Observer::StopTimer(const std::string& timer_name) {
  auto it = timers_.find(timer_name);

  DCHECK(it != timers_.end());

  auto start = it->second;
  timers_.erase(it);
  auto now = base::TimeTicks::Now();
  auto duration_ms = (now - start).InMilliseconds();

  VLOG(1) << "Stop timer |" << timer_name << "|, time elapsed: " << duration_ms
          << "ms.\n";

  if (metrics_) {
    metrics_->SendToUMA(timer_name, duration_ms, kTimerMinMs_, kTimerMaxMs_,
                        kTimerBuckets_);
  }
}

void Observer::SetMetricsLibrary(
    std::unique_ptr<MetricsLibraryInterface> metrics) {
  metrics_ = std::move(metrics);
}

void Observer::RecordHwVerificationReport(const HwVerificationReport& report) {
  {
    auto key = base::StrCat({kMetricVerifierReportPrefix, "IsCompliant"});
    LOG(INFO) << key << ": " << report.is_compliant();
    if (metrics_) {
      metrics_->SendBoolToUMA(key, report.is_compliant());
    }
  }

  for (auto i = 0; i < report.found_component_infos_size(); i++) {
    const auto& info = report.found_component_infos(i);
    const auto& name = runtime_probe::ProbeRequest_SupportCategory_Name(
        info.component_category());
    const auto& qualification_status = info.qualification_status();

    const std::string uma_key =
        base::StrCat({kMetricVerifierReportPrefix, name});

    LOG(INFO) << uma_key << ": "
              << QualificationStatus_Name(qualification_status);
    if (metrics_) {
      metrics_->SendEnumToUMA(uma_key, qualification_status,
                              QualificationStatus_ARRAYSIZE);
    }
  }
  RecordStructuredHwVerificationReport(report);
}

}  // namespace hardware_verifier
