// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "featured/feature_library.h"

#include <utility>

#include <base/functional/bind.h>
#include <base/functional/callback_helpers.h>
#include <base/logging.h>
#include <brillo/dbus/dbus_connection.h>
#include <brillo/dbus/dbus_method_invoker.h>
#include <brillo/dbus/dbus_proxy_util.h>
#include <brillo/errors/error.h>
#include <chromeos/dbus/service_constants.h>

namespace feature {

constexpr char kFeatureLibInterface[] = "org.chromium.feature_lib";
constexpr char kFeatureLibPath[] = "/org/chromium/feature_lib";
constexpr char kRefetchSignal[] = "RefetchFeatureState";

PlatformFeatures::PlatformFeatures(scoped_refptr<dbus::Bus> bus,
                                   dbus::ObjectProxy* chrome_proxy,
                                   dbus::ObjectProxy* feature_proxy)
    : bus_(bus), chrome_proxy_(chrome_proxy), feature_proxy_(feature_proxy) {}

std::unique_ptr<PlatformFeatures> PlatformFeatures::New(
    scoped_refptr<dbus::Bus> bus) {
  auto* chrome_proxy = bus->GetObjectProxy(
      chromeos::kChromeFeaturesServiceName,
      dbus::ObjectPath(chromeos::kChromeFeaturesServicePath));
  if (!chrome_proxy) {
    LOG(ERROR) << "Failed to create object proxy for "
               << chromeos::kChromeFeaturesServiceName;
    return nullptr;
  }

  auto* feature_proxy = bus->GetObjectProxy(kFeatureLibInterface,
                                            dbus::ObjectPath(kFeatureLibPath));
  if (!feature_proxy) {
    LOG(ERROR) << "Failed to create object proxy for " << kFeatureLibInterface;
    return nullptr;
  }

  return std::unique_ptr<PlatformFeatures>(
      new PlatformFeatures(bus, chrome_proxy, feature_proxy));
}

void PlatformFeatures::IsEnabled(const VariationsFeature& feature,
                                 IsEnabledCallback callback) {
  DCHECK(CheckFeatureIdentity(feature)) << feature.name;

  chrome_proxy_->WaitForServiceToBeAvailable(base::BindOnce(
      &PlatformFeatures::OnWaitForServiceIsEnabled,
      weak_ptr_factory_.GetWeakPtr(), feature, std::move(callback)));
}

bool PlatformFeatures::IsEnabledBlocking(const VariationsFeature& feature) {
  DCHECK(CheckFeatureIdentity(feature)) << feature.name;

  dbus::MethodCall call(chromeos::kChromeFeaturesServiceInterface,
                        chromeos::kChromeFeaturesServiceIsFeatureEnabledMethod);
  dbus::MessageWriter writer(&call);
  writer.AppendString(feature.name);
  std::unique_ptr<dbus::Response> response = brillo::dbus_utils::CallDBusMethod(
      bus_, chrome_proxy_, &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  if (!response) {
    return feature.default_state == FEATURE_ENABLED_BY_DEFAULT;
  }

  dbus::MessageReader reader(response.get());
  bool feature_enabled = false;
  if (!reader.PopBool(&feature_enabled)) {
    LOG(ERROR) << "failed to read bool from dbus result; using default value";
    return feature.default_state == FEATURE_ENABLED_BY_DEFAULT;
  }

  return feature_enabled;
}

void PlatformFeatures::OnWaitForServiceIsEnabled(
    const VariationsFeature& feature,
    IsEnabledCallback callback,
    bool available) {
  if (!available) {
    std::move(callback).Run(feature.default_state ==
                            FEATURE_ENABLED_BY_DEFAULT);
    LOG(ERROR) << "failed to connect to dbus service; using default value";
    return;
  }
  dbus::MethodCall call(chromeos::kChromeFeaturesServiceInterface,
                        chromeos::kChromeFeaturesServiceIsFeatureEnabledMethod);
  dbus::MessageWriter writer(&call);
  writer.AppendString(feature.name);
  chrome_proxy_->CallMethod(
      &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
      base::BindOnce(&PlatformFeatures::HandleIsEnabledResponse,
                     weak_ptr_factory_.GetWeakPtr(), feature,
                     std::move(callback)));
}

void PlatformFeatures::HandleIsEnabledResponse(const VariationsFeature& feature,
                                               IsEnabledCallback callback,
                                               dbus::Response* response) {
  if (!response) {
    LOG(ERROR) << "dbus call failed; using default value";
    std::move(callback).Run(feature.default_state ==
                            FEATURE_ENABLED_BY_DEFAULT);
    return;
  }

  dbus::MessageReader reader(response);
  bool feature_enabled = false;
  if (!reader.PopBool(&feature_enabled)) {
    LOG(ERROR) << "failed to read bool from dbus result; using default value";
    std::move(callback).Run(feature.default_state ==
                            FEATURE_ENABLED_BY_DEFAULT);
    return;
  }

  std::move(callback).Run(feature_enabled);
}

void PlatformFeatures::GetParamsAndEnabled(
    const std::vector<const VariationsFeature*>& features,
    GetParamsCallback callback) {
  for (const auto* feature : features) {
    DCHECK(CheckFeatureIdentity(*feature)) << feature->name;
  }

  chrome_proxy_->WaitForServiceToBeAvailable(base::BindOnce(
      &PlatformFeatures::OnWaitForServiceGetParams,
      weak_ptr_factory_.GetWeakPtr(), features, std::move(callback)));
}

PlatformFeaturesInterface::ParamsResult
PlatformFeatures::GetParamsAndEnabledBlocking(
    const std::vector<const VariationsFeature*>& features) {
  for (const auto* feature : features) {
    DCHECK(CheckFeatureIdentity(*feature)) << feature->name;
  }

  dbus::MethodCall call(chromeos::kChromeFeaturesServiceInterface,
                        chromeos::kChromeFeaturesServiceGetFeatureParamsMethod);
  dbus::MessageWriter writer(&call);
  EncodeGetParamsArgument(&writer, features);
  std::unique_ptr<dbus::Response> response = brillo::dbus_utils::CallDBusMethod(
      bus_, chrome_proxy_, &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  return ParseGetParamsResponse(response.get(), features);
}

void PlatformFeatures::EncodeGetParamsArgument(
    dbus::MessageWriter* writer,
    const std::vector<const VariationsFeature*>& features) {
  dbus::MessageWriter array_writer(nullptr);
  writer->OpenArray("s", &array_writer);
  for (const auto* feature : features) {
    array_writer.AppendString(feature->name);
  }
  writer->CloseContainer(&array_writer);
}

PlatformFeaturesInterface::ParamsResult
PlatformFeatures::CreateDefaultGetParamsAndEnabledResponse(
    const std::vector<const VariationsFeature*>& features) {
  std::map<std::string, ParamsResultEntry> default_response;
  for (const auto* feature : features) {
    default_response[feature->name] = ParamsResultEntry{
        .enabled = feature->default_state == FEATURE_ENABLED_BY_DEFAULT,
    };
  }
  return default_response;
}

void PlatformFeatures::OnWaitForServiceGetParams(
    const std::vector<const VariationsFeature*>& features,
    GetParamsCallback callback,
    bool available) {
  if (!available) {
    LOG(ERROR) << "failed to connect to dbus service; using default value";
    std::move(callback).Run(CreateDefaultGetParamsAndEnabledResponse(features));
    return;
  }
  dbus::MethodCall call(chromeos::kChromeFeaturesServiceInterface,
                        chromeos::kChromeFeaturesServiceGetFeatureParamsMethod);
  dbus::MessageWriter writer(&call);
  EncodeGetParamsArgument(&writer, features);
  chrome_proxy_->CallMethod(
      &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
      base::BindOnce(&PlatformFeatures::HandleGetParamsResponse,
                     weak_ptr_factory_.GetWeakPtr(), features,
                     std::move(callback)));
}

void PlatformFeatures::HandleGetParamsResponse(
    const std::vector<const VariationsFeature*>& features,
    GetParamsCallback callback,
    dbus::Response* response) {
  std::move(callback).Run(ParseGetParamsResponse(response, features));
}

PlatformFeatures::ParamsResult PlatformFeatures::ParseGetParamsResponse(
    dbus::Response* response,
    const std::vector<const VariationsFeature*>& features) {
  // Parse the response, which should be an array containing dict entries which
  // maps feature names to a struct containing:
  // * A bool for whether to use the overridden feature enable state
  // * A bool indicating the enable state (only valid if the first bool is true)
  // * A (possibly-empty) array of dict entries mapping parameter keys to values
  if (!response) {
    LOG(ERROR) << "dbus call failed; using default value";
    return CreateDefaultGetParamsAndEnabledResponse(features);
  }

  dbus::MessageReader reader(response);
  dbus::MessageReader array_reader(nullptr);
  if (!reader.PopArray(&array_reader)) {
    LOG(ERROR) << "failed to read array from dbus result; using default value";
    return CreateDefaultGetParamsAndEnabledResponse(features);
  }

  std::map<std::string, ParamsResultEntry> result;
  while (array_reader.HasMoreData()) {
    ParamsResultEntry entry;

    dbus::MessageReader feature_entry_reader(nullptr);
    if (!array_reader.PopDictEntry(&feature_entry_reader)) {
      LOG(ERROR) << "Failed to read dict from dbus result; using default.";
      return CreateDefaultGetParamsAndEnabledResponse(features);
    }

    // Get name
    std::string feature_name;
    if (!feature_entry_reader.PopString(&feature_name)) {
      LOG(ERROR) << "Failed to read string from dbus result; using default "
                 << "value";
      return CreateDefaultGetParamsAndEnabledResponse(features);
    }

    dbus::MessageReader struct_reader(nullptr);
    if (!feature_entry_reader.PopStruct(&struct_reader)) {
      LOG(ERROR) << "Failed to read struct from dbus result; using default "
                 << "value";
      return CreateDefaultGetParamsAndEnabledResponse(features);
    }

    // Get override state.
    bool use_override = false;
    bool override_value = false;
    if (!struct_reader.PopBool(&use_override) ||
        !struct_reader.PopBool(&override_value)) {
      LOG(ERROR) << "Failed to pop a bool; using default value";
      return CreateDefaultGetParamsAndEnabledResponse(features);
    } else {
      if (use_override) {
        entry.enabled = override_value;
      } else {
        // This is mildly inefficient, but the number of features passed to this
        // method is expected to be small (human magnitude), so it isn't a
        // prohibitive cost.
        for (const auto* feature : features) {
          if (feature->name == feature_name) {
            entry.enabled =
                feature->default_state == FEATURE_ENABLED_BY_DEFAULT;
          }
        }
      }
    }

    // Finally, get params.
    std::map<std::string, std::string> params;
    dbus::MessageReader params_array_reader(nullptr);
    if (!struct_reader.PopArray(&params_array_reader)) {
      LOG(ERROR) << "Failed to read params array; using default value";
      return CreateDefaultGetParamsAndEnabledResponse(features);
    }
    while (params_array_reader.HasMoreData()) {
      dbus::MessageReader entry_reader(nullptr);
      std::string key;
      std::string value;
      if (!params_array_reader.PopDictEntry(&entry_reader) ||
          !entry_reader.PopString(&key) || !entry_reader.PopString(&value)) {
        LOG(ERROR) << "failed to read dict entry; using default value";
        return CreateDefaultGetParamsAndEnabledResponse(features);
      }
      params[key] = value;
    }
    entry.params = std::move(params);

    result[feature_name] = entry;
  }

  return result;
}

bool PlatformFeatures::CheckFeatureIdentity(const VariationsFeature& feature) {
  base::AutoLock auto_lock(lock_);

  auto it = feature_identity_tracker_.find(feature.name);
  if (it == feature_identity_tracker_.end()) {
    // If it's not tracked yet, register it.
    feature_identity_tracker_[feature.name] = &feature;
    return true;
  }
  // Compare address of |feature| to the existing tracked entry.
  return it->second == &feature;
}

void PlatformFeatures::ShutdownBus() {
  bus_->ShutdownAndBlock();
}

void PlatformFeatures::ListenForRefetchNeeded(
    base::RepeatingCallback<void(void)> signal_callback,
    base::OnceCallback<void(bool)> attached_callback) {
  feature_proxy_->ConnectToSignal(
      kFeatureLibInterface, kRefetchSignal,
      base::IgnoreArgs<dbus::Signal*>(signal_callback),
      base::BindOnce(&PlatformFeatures::OnConnectedCallback,
                     std::move(attached_callback)));
}

// static
void PlatformFeatures::OnConnectedCallback(
    base::OnceCallback<void(bool)> attached_callback,
    const std::string& interface,
    const std::string& signal,
    bool success) {
  if (!success) {
    LOG(ERROR) << "Failed to connect to " << interface << "." << signal;
  }
  std::move(attached_callback).Run(success);
}

}  // namespace feature
