// 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 "diagnostics/cros_healthd/cros_healthd_routine_service.h"

#include <limits>
#include <string>
#include <utility>
#include <vector>

#include <base/logging.h>
#include <base/time/time.h>

#include "diagnostics/common/system/debugd_adapter.h"
#include "diagnostics/cros_healthd/system/system_config.h"
#include "mojo/cros_healthd_diagnostics.mojom.h"
#include "mojo/nullable_primitives.mojom.h"

namespace diagnostics {

namespace mojo_ipc = ::chromeos::cros_healthd::mojom;

namespace {

void SetErrorRoutineUpdate(const std::string& status_message,
                           mojo_ipc::RoutineUpdate* response) {
  mojo_ipc::NonInteractiveRoutineUpdate noninteractive_update;
  noninteractive_update.status = mojo_ipc::DiagnosticRoutineStatusEnum::kError;
  noninteractive_update.status_message = status_message;
  response->routine_update_union->set_noninteractive_update(
      noninteractive_update.Clone());
  response->progress_percent = 0;
}

}  // namespace

CrosHealthdRoutineService::CrosHealthdRoutineService(
    Context* context, CrosHealthdRoutineFactory* routine_factory)
    : context_(context), routine_factory_(routine_factory) {
  DCHECK(context_);
  DCHECK(routine_factory_);
  PopulateAvailableRoutines();
}

CrosHealthdRoutineService::~CrosHealthdRoutineService() = default;

void CrosHealthdRoutineService::GetAvailableRoutines(
    GetAvailableRoutinesCallback callback) {
  std::move(callback).Run(std::vector<mojo_ipc::DiagnosticRoutineEnum>(
      available_routines_.begin(), available_routines_.end()));
}

void CrosHealthdRoutineService::GetRoutineUpdate(
    int32_t id,
    mojo_ipc::DiagnosticRoutineCommandEnum command,
    bool include_output,
    GetRoutineUpdateCallback callback) {
  mojo_ipc::RoutineUpdate update{0, mojo::ScopedHandle(),
                                 mojo_ipc::RoutineUpdateUnion::New()};

  auto itr = active_routines_.find(id);
  if (itr == active_routines_.end()) {
    LOG(ERROR) << "Bad id in GetRoutineUpdateRequest: " << id;
    SetErrorRoutineUpdate("Specified routine does not exist.", &update);
    std::move(callback).Run(mojo_ipc::RoutineUpdate::New(
        update.progress_percent, std::move(update.output),
        std::move(update.routine_update_union)));
    return;
  }

  auto* routine = itr->second.get();
  switch (command) {
    case mojo_ipc::DiagnosticRoutineCommandEnum::kContinue:
      routine->Resume();
      break;
    case mojo_ipc::DiagnosticRoutineCommandEnum::kCancel:
      routine->Cancel();
      break;
    case mojo_ipc::DiagnosticRoutineCommandEnum::kGetStatus:
      // Retrieving the status and output of a routine is handled below.
      break;
    case mojo_ipc::DiagnosticRoutineCommandEnum::kRemove:
      routine->PopulateStatusUpdate(&update, include_output);
      if (update.routine_update_union->is_noninteractive_update()) {
        update.routine_update_union->get_noninteractive_update()->status =
            mojo_ipc::DiagnosticRoutineStatusEnum::kRemoved;
      }
      active_routines_.erase(itr);
      // |routine| is invalid at this point!
      std::move(callback).Run(mojo_ipc::RoutineUpdate::New(
          update.progress_percent, std::move(update.output),
          std::move(update.routine_update_union)));
      return;
  }

  routine->PopulateStatusUpdate(&update, include_output);
  std::move(callback).Run(mojo_ipc::RoutineUpdate::New(
      update.progress_percent, std::move(update.output),
      std::move(update.routine_update_union)));
}

void CrosHealthdRoutineService::RunAcPowerRoutine(
    mojo_ipc::AcPowerStatusEnum expected_status,
    const base::Optional<std::string>& expected_power_type,
    RunAcPowerRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeAcPowerRoutine(expected_status,
                                                  expected_power_type),
             mojo_ipc::DiagnosticRoutineEnum::kAcPower, std::move(callback));
}

void CrosHealthdRoutineService::RunBatteryCapacityRoutine(
    RunBatteryCapacityRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeBatteryCapacityRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity,
             std::move(callback));
}

void CrosHealthdRoutineService::RunBatteryChargeRoutine(
    uint32_t length_seconds,
    uint32_t minimum_charge_percent_required,
    RunBatteryChargeRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeBatteryChargeRoutine(
                 base::TimeDelta::FromSeconds(length_seconds),
                 minimum_charge_percent_required),
             mojo_ipc::DiagnosticRoutineEnum::kBatteryCharge,
             std::move(callback));
}

void CrosHealthdRoutineService::RunBatteryDischargeRoutine(
    uint32_t length_seconds,
    uint32_t maximum_discharge_percent_allowed,
    RunBatteryDischargeRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeBatteryDischargeRoutine(
                 base::TimeDelta::FromSeconds(length_seconds),
                 maximum_discharge_percent_allowed),
             mojo_ipc::DiagnosticRoutineEnum::kBatteryDischarge,
             std::move(callback));
}

void CrosHealthdRoutineService::RunBatteryHealthRoutine(
    RunBatteryHealthRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeBatteryHealthRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kBatteryHealth,
             std::move(callback));
}

void CrosHealthdRoutineService::RunCaptivePortalRoutine(
    RunCaptivePortalRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeCaptivePortalRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kCaptivePortal,
             std::move(callback));
}

void CrosHealthdRoutineService::RunCpuCacheRoutine(
    chromeos::cros_healthd::mojom::NullableUint32Ptr length_seconds,
    RunCpuCacheRoutineCallback callback) {
  base::Optional<base::TimeDelta> exec_duration;
  if (!length_seconds.is_null())
    exec_duration = base::TimeDelta::FromSeconds(length_seconds->value);
  RunRoutine(routine_factory_->MakeCpuCacheRoutine(exec_duration),
             mojo_ipc::DiagnosticRoutineEnum::kCpuCache, std::move(callback));
}

void CrosHealthdRoutineService::RunCpuStressRoutine(
    chromeos::cros_healthd::mojom::NullableUint32Ptr length_seconds,
    RunCpuStressRoutineCallback callback) {
  base::Optional<base::TimeDelta> exec_duration;
  if (!length_seconds.is_null())
    exec_duration = base::TimeDelta::FromSeconds(length_seconds->value);
  RunRoutine(routine_factory_->MakeCpuStressRoutine(exec_duration),
             mojo_ipc::DiagnosticRoutineEnum::kCpuStress, std::move(callback));
}

void CrosHealthdRoutineService::RunDiskReadRoutine(
    mojo_ipc::DiskReadRoutineTypeEnum type,
    uint32_t length_seconds,
    uint32_t file_size_mb,
    RunDiskReadRoutineCallback callback) {
  RunRoutine(
      routine_factory_->MakeDiskReadRoutine(
          type, base::TimeDelta::FromSeconds(length_seconds), file_size_mb),
      mojo_ipc::DiagnosticRoutineEnum::kDiskRead, std::move(callback));
}

void CrosHealthdRoutineService::RunDnsLatencyRoutine(
    RunDnsLatencyRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeDnsLatencyRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kDnsLatency, std::move(callback));
}

void CrosHealthdRoutineService::RunDnsResolutionRoutine(
    RunDnsResolutionRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeDnsResolutionRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kDnsResolution,
             std::move(callback));
}

void CrosHealthdRoutineService::RunDnsResolverPresentRoutine(
    RunDnsResolverPresentRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeDnsResolverPresentRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kDnsResolverPresent,
             std::move(callback));
}

void CrosHealthdRoutineService::RunFloatingPointAccuracyRoutine(
    chromeos::cros_healthd::mojom::NullableUint32Ptr length_seconds,
    RunFloatingPointAccuracyRoutineCallback callback) {
  base::Optional<base::TimeDelta> exec_duration;
  if (!length_seconds.is_null())
    exec_duration = base::TimeDelta::FromSeconds(length_seconds->value);
  RunRoutine(routine_factory_->MakeFloatingPointAccuracyRoutine(exec_duration),
             mojo_ipc::DiagnosticRoutineEnum::kFloatingPointAccuracy,
             std::move(callback));
}

void CrosHealthdRoutineService::RunGatewayCanBePingedRoutine(
    RunGatewayCanBePingedRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeGatewayCanBePingedRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kGatewayCanBePinged,
             std::move(callback));
}

void CrosHealthdRoutineService::RunHasSecureWiFiConnectionRoutine(
    RunHasSecureWiFiConnectionRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeHasSecureWiFiConnectionRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kHasSecureWiFiConnection,
             std::move(callback));
}

void CrosHealthdRoutineService::RunHttpFirewallRoutine(
    RunHttpFirewallRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeHttpFirewallRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kHttpFirewall,
             std::move(callback));
}

void CrosHealthdRoutineService::RunHttpsFirewallRoutine(
    RunHttpsFirewallRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeHttpsFirewallRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kHttpsFirewall,
             std::move(callback));
}

void CrosHealthdRoutineService::RunHttpsLatencyRoutine(
    RunHttpsLatencyRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeHttpsLatencyRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kHttpsLatency,
             std::move(callback));
}

void CrosHealthdRoutineService::RunLanConnectivityRoutine(
    RunLanConnectivityRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeLanConnectivityRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kLanConnectivity,
             std::move(callback));
}

void CrosHealthdRoutineService::RunMemoryRoutine(
    RunMemoryRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeMemoryRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kMemory, std::move(callback));
}

void CrosHealthdRoutineService::RunNvmeSelfTestRoutine(
    mojo_ipc::NvmeSelfTestTypeEnum nvme_self_test_type,
    RunNvmeSelfTestRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeNvmeSelfTestRoutine(
                 context_->debugd_adapter(), nvme_self_test_type),
             mojo_ipc::DiagnosticRoutineEnum::kNvmeSelfTest,
             std::move(callback));
}

void CrosHealthdRoutineService::RunNvmeWearLevelRoutine(
    uint32_t wear_level_threshold, RunNvmeWearLevelRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeNvmeWearLevelRoutine(
                 context_->debugd_adapter(), wear_level_threshold),
             mojo_ipc::DiagnosticRoutineEnum::kNvmeWearLevel,
             std::move(callback));
}

void CrosHealthdRoutineService::RunPrimeSearchRoutine(
    chromeos::cros_healthd::mojom::NullableUint32Ptr length_seconds,
    RunPrimeSearchRoutineCallback callback) {
  base::Optional<base::TimeDelta> exec_duration;
  if (!length_seconds.is_null())
    exec_duration = base::TimeDelta::FromSeconds(length_seconds->value);
  RunRoutine(routine_factory_->MakePrimeSearchRoutine(exec_duration),
             mojo_ipc::DiagnosticRoutineEnum::kPrimeSearch,
             std::move(callback));
}

void CrosHealthdRoutineService::RunSignalStrengthRoutine(
    RunSignalStrengthRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeSignalStrengthRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kSignalStrength,
             std::move(callback));
}

void CrosHealthdRoutineService::RunSmartctlCheckRoutine(
    RunSmartctlCheckRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeSmartctlCheckRoutine(),
             mojo_ipc::DiagnosticRoutineEnum::kSmartctlCheck,
             std::move(callback));
}

void CrosHealthdRoutineService::RunUrandomRoutine(
    mojo_ipc::NullableUint32Ptr length_seconds,
    RunUrandomRoutineCallback callback) {
  RunRoutine(routine_factory_->MakeUrandomRoutine(std::move(length_seconds)),
             mojo_ipc::DiagnosticRoutineEnum::kUrandom, std::move(callback));
}

void CrosHealthdRoutineService::RunRoutine(
    std::unique_ptr<DiagnosticRoutine> routine,
    mojo_ipc::DiagnosticRoutineEnum routine_enum,
    base::OnceCallback<void(mojo_ipc::RunRoutineResponsePtr)> callback) {
  DCHECK(routine);

  if (!available_routines_.count(routine_enum)) {
    LOG(ERROR) << routine_enum << " is not supported on this device";
    std::move(callback).Run(mojo_ipc::RunRoutineResponse::New(
        mojo_ipc::kFailedToStartId,
        mojo_ipc::DiagnosticRoutineStatusEnum::kUnsupported));
    return;
  }

  CHECK(next_id_ < std::numeric_limits<int32_t>::max())
      << "Maximum number of routines exceeded.";

  routine->Start();
  int32_t id = next_id_;
  DCHECK(active_routines_.find(id) == active_routines_.end());
  active_routines_[id] = std::move(routine);
  ++next_id_;

  std::move(callback).Run(
      mojo_ipc::RunRoutineResponse::New(id, active_routines_[id]->GetStatus()));
}

void CrosHealthdRoutineService::PopulateAvailableRoutines() {
  // Routines that are supported on all devices.
  available_routines_ = {
      mojo_ipc::DiagnosticRoutineEnum::kUrandom,
      mojo_ipc::DiagnosticRoutineEnum::kAcPower,
      mojo_ipc::DiagnosticRoutineEnum::kCpuCache,
      mojo_ipc::DiagnosticRoutineEnum::kCpuStress,
      mojo_ipc::DiagnosticRoutineEnum::kFloatingPointAccuracy,
      mojo_ipc::DiagnosticRoutineEnum::kPrimeSearch,
      mojo_ipc::DiagnosticRoutineEnum::kMemory,
      mojo_ipc::DiagnosticRoutineEnum::kLanConnectivity,
      mojo_ipc::DiagnosticRoutineEnum::kSignalStrength,
      mojo_ipc::DiagnosticRoutineEnum::kGatewayCanBePinged,
      mojo_ipc::DiagnosticRoutineEnum::kHasSecureWiFiConnection,
      mojo_ipc::DiagnosticRoutineEnum::kDnsResolverPresent,
      mojo_ipc::DiagnosticRoutineEnum::kDnsLatency,
      mojo_ipc::DiagnosticRoutineEnum::kDnsResolution,
      mojo_ipc::DiagnosticRoutineEnum::kCaptivePortal,
      mojo_ipc::DiagnosticRoutineEnum::kHttpFirewall,
      mojo_ipc::DiagnosticRoutineEnum::kHttpsFirewall,
      mojo_ipc::DiagnosticRoutineEnum::kHttpsLatency};

  if (context_->system_config()->HasBattery()) {
    available_routines_.insert(
        mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity);
    available_routines_.insert(mojo_ipc::DiagnosticRoutineEnum::kBatteryHealth);
    available_routines_.insert(
        mojo_ipc::DiagnosticRoutineEnum::kBatteryDischarge);
    available_routines_.insert(mojo_ipc::DiagnosticRoutineEnum::kBatteryCharge);
  }

  if (context_->system_config()->NvmeSupported()) {
    if (context_->system_config()->IsWilcoDevice()) {
      available_routines_.insert(
          mojo_ipc::DiagnosticRoutineEnum::kNvmeWearLevel);
    }
    available_routines_.insert(mojo_ipc::DiagnosticRoutineEnum::kNvmeSelfTest);
  }

  if (context_->system_config()->SmartCtlSupported()) {
    available_routines_.insert(mojo_ipc::DiagnosticRoutineEnum::kSmartctlCheck);
  }

  if (context_->system_config()->FioSupported()) {
    available_routines_.insert(mojo_ipc::DiagnosticRoutineEnum::kDiskRead);
  }
}

}  // namespace diagnostics
