// Copyright 2018 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 "bluetooth/newblued/advertising_manager_interface_handler.h"

#include <memory>
#include <utility>

#include <base/bind.h>
#include <base/callback.h>
#include <base/stl_util.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>
#include <dbus/object_path.h>
#include <dbus/object_proxy.h>
#include <dbus/property.h>

#include "bluetooth/common/util.h"
#include "bluetooth/newblued/uuid.h"

namespace bluetooth {

class AdvertisementProperties : public dbus::PropertySet {
 public:
  AdvertisementProperties(dbus::ObjectProxy* object_proxy,
                          const base::Callback<bool()>& on_removed)
      : dbus::PropertySet(
            object_proxy,
            bluetooth_advertisement::kBluetoothAdvertisementInterface,
            base::Bind(&AdvertisementProperties::OnChange,
                       base::Unretained(this),
                       on_removed)) {
    RegisterProperty(bluetooth_advertisement::kTypeProperty, &type);
    RegisterProperty(bluetooth_advertisement::kIncludeTxPowerProperty,
                     &include_tx_power);
    RegisterProperty(bluetooth_advertisement::kServiceUUIDsProperty,
                     &service_uuids);
    RegisterProperty(bluetooth_advertisement::kSolicitUUIDsProperty,
                     &solicit_uuids);
    RegisterProperty(bluetooth_advertisement::kManufacturerDataProperty,
                     &manufacturer_data);
    RegisterProperty(bluetooth_advertisement::kServiceDataProperty,
                     &service_data);
  }

  bool Init(brillo::ErrorPtr* error) {
    dbus::MethodCall method_call(dbus::kPropertiesInterface,
                                 dbus::kPropertiesGetAll);
    dbus::MessageWriter writer(&method_call);
    writer.AppendString(interface());
    std::unique_ptr<dbus::Response> response(object_proxy()->CallMethodAndBlock(
        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
    if (!response) {
      brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_advertising_manager::kErrorDoesNotExist,
                           "Advertisement object does not exist");
      return false;
    }

    OnGetAll(response.get());
    return true;
  }

  void OnChange(const base::Callback<bool()>& on_removed,
                const std::string& name) {
    // An advertisement object is considered removed if "Type" is not valid,
    // which is a mandatory property.
    if (name == bluetooth_advertisement::kTypeProperty && !type.is_valid())
      on_removed.Run();
  }

  dbus::Property<std::string> type;
  dbus::Property<bool> include_tx_power;
  dbus::Property<std::vector<std::string>> service_uuids;
  dbus::Property<std::vector<std::string>> solicit_uuids;
  dbus::Property<std::map<uint16_t, std::vector<uint8_t>>> manufacturer_data;
  dbus::Property<std::map<std::string, std::vector<uint8_t>>> service_data;
};

AdvertisingManagerInterfaceHandler::AdvertisingManagerInterfaceHandler(
    LibNewblue* libnewblue,
    scoped_refptr<dbus::Bus> bus,
    ExportedObjectManagerWrapper* exported_object_manager_wrapper)
    : libnewblue_(std::move(libnewblue)),
      bus_(bus),
      exported_object_manager_wrapper_(exported_object_manager_wrapper) {}

void AdvertisingManagerInterfaceHandler::Init() {
  dbus::ObjectPath adapter_object_path(kAdapterObjectPath);
  exported_object_manager_wrapper_->AddExportedInterface(
      adapter_object_path,
      bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface);
  ExportedInterface* advertising_manager_interface =
      exported_object_manager_wrapper_->GetExportedInterface(
          adapter_object_path,
          bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface);

  advertising_manager_interface
      ->EnsureExportedPropertyRegistered<bool>(
          bluetooth_advertising_manager::kIsTXPowerSupportedProperty)
      ->SetValue(libnewblue_->HciAdvIsPowerLevelSettingSupported());
  advertising_manager_interface->AddSimpleMethodHandlerWithErrorAndMessage(
      bluetooth_advertising_manager::kRegisterAdvertisement,
      base::Unretained(this),
      &AdvertisingManagerInterfaceHandler::HandleRegisterAdvertisement);
  advertising_manager_interface->AddSimpleMethodHandlerWithErrorAndMessage(
      bluetooth_advertising_manager::kUnregisterAdvertisement,
      base::Unretained(this),
      &AdvertisingManagerInterfaceHandler::HandleUnregisterAdvertisement);
  advertising_manager_interface->ExportAndBlock();
}

bool AdvertisingManagerInterfaceHandler::HandleRegisterAdvertisement(
    brillo::ErrorPtr* error,
    dbus::Message* message,
    dbus::ObjectPath object_path,
    brillo::VariantDictionary options) {
  if (base::ContainsKey(handles_, object_path)) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorFailed,
                         "Advertisement already registered");
    return false;
  }

  hci_adv_set_t handle = libnewblue_->HciAdvSetAllocate();
  if (!handle) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorFailed,
                         "Cannot allocate advertisement handle");
    return false;
  }

  AdvertisementProperties properties(
      bus_->GetObjectProxy(message->GetSender(), object_path),
      base::Bind(
          &AdvertisingManagerInterfaceHandler::HandleUnregisterAdvertisement,
          base::Unretained(this), nullptr, nullptr, object_path));
  std::vector<uint8_t> data;
  if (!properties.Init(error) || !ConstructData(properties, &data, error) ||
      !ConfigureData(handle, data, error) || !SetParams(handle, error) ||
      !Enable(handle, error)) {
    libnewblue_->HciAdvSetFree(handle);
    return false;
  }

  handles_[object_path] = handle;
  return true;
}

bool AdvertisingManagerInterfaceHandler::HandleUnregisterAdvertisement(
    brillo::ErrorPtr* error,
    dbus::Message* message,
    dbus::ObjectPath object_path) {
  auto it = handles_.find(object_path);
  if (it == handles_.end()) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorDoesNotExist,
                         "Advertisement not registered");
    return false;
  }

  libnewblue_->HciAdvSetDisable(it->second);
  libnewblue_->HciAdvSetFree(it->second);
  handles_.erase(it);
  return true;
}

bool AdvertisingManagerInterfaceHandler::AddType(const std::string& type,
                                                 std::vector<uint8_t>* data,
                                                 brillo::ErrorPtr* error) {
  constexpr uint8_t kGeneralDiscoverable = 2;
  if (type == bluetooth_advertisement::kTypeBroadcast)
    return true;

  if (type == bluetooth_advertisement::kTypePeripheral) {
    data->push_back(2);
    data->push_back(HCI_EIR_TYPE_FLAGS);
    data->push_back(kGeneralDiscoverable);
    return true;
  }

  brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                       bluetooth_advertising_manager::kErrorInvalidArguments,
                       "Advertisement type invalid");
  return false;
}

bool AdvertisingManagerInterfaceHandler::AddIncludeTxPower(
    bool include_tx_power,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  if (!include_tx_power)
    return true;

  data->push_back(2);
  data->push_back(HCI_EIR_TX_POWER_LEVEL);
  data->push_back(HCI_ADV_TX_PWR_LVL_DONT_CARE);
  return true;
}

bool AdvertisingManagerInterfaceHandler::AddServiceUuid(
    const std::vector<std::string>& service_uuids,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  for (const std::string& service_uuid : service_uuids) {
    Uuid uuid(service_uuid);
    if (uuid.format() == UuidFormat::UUID_INVALID) {
      brillo::Error::AddTo(
          error, FROM_HERE, brillo::errors::dbus::kDomain,
          bluetooth_advertising_manager::kErrorInvalidArguments,
          "Service uuid invalid");
      return false;
    }

    data->push_back(kUuid128Size + 1);
    data->push_back(HCI_EIR_TYPE_COMPL_LIST_UUID128);
    data->insert(data->end(), uuid.value().rbegin(), uuid.value().rend());
  }
  return true;
}

bool AdvertisingManagerInterfaceHandler::AddSolicitUuid(
    const std::vector<std::string>& solicit_uuids,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  for (const std::string& solicit_uuid : solicit_uuids) {
    Uuid uuid(solicit_uuid);
    if (uuid.format() == UuidFormat::UUID_INVALID) {
      brillo::Error::AddTo(
          error, FROM_HERE, brillo::errors::dbus::kDomain,
          bluetooth_advertising_manager::kErrorInvalidArguments,
          "Solicit uuid invalid");
      return false;
    }

    data->push_back(kUuid128Size + 1);
    data->push_back(HCI_EIR_SVC_SOLICITS_UUID128);
    data->insert(data->end(), uuid.value().rbegin(), uuid.value().rend());
  }
  return true;
}

bool AdvertisingManagerInterfaceHandler::AddServiceData(
    const std::map<std::string, std::vector<uint8_t>>& service_data,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  for (const auto& uuid_data : service_data) {
    Uuid uuid(uuid_data.first);
    if (uuid.format() == UuidFormat::UUID_INVALID) {
      brillo::Error::AddTo(
          error, FROM_HERE, brillo::errors::dbus::kDomain,
          bluetooth_advertising_manager::kErrorInvalidArguments,
          "Service data uuid invalid");
      return false;
    }

    size_t length = uuid_data.second.size() + kUuid128Size + 1;
    if (length > UINT8_MAX) {
      brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_advertising_manager::kErrorInvalidLength,
                           "Service data too long");
      return false;
    }

    data->push_back(length);
    data->push_back(HCI_EIR_SVC_DATA_UUID128);
    data->insert(data->end(), uuid.value().rbegin(), uuid.value().rend());
    data->insert(data->end(), uuid_data.second.rbegin(),
                 uuid_data.second.rend());
  }
  return true;
}

bool AdvertisingManagerInterfaceHandler::AddManufacturerData(
    const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  for (const auto& id_data : manufacturer_data) {
    size_t length = id_data.second.size() + sizeof(uint16_t) + 1;
    if (length > UINT8_MAX) {
      brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_advertising_manager::kErrorInvalidLength,
                           "Manufacturer data too long");
      return false;
    }

    data->push_back(length);
    data->push_back(HCI_EIR_MANUF_DATA);
    data->push_back(id_data.first & 0xff);
    data->push_back(id_data.first >> 8);
    data->insert(data->end(), id_data.second.rbegin(), id_data.second.rend());
  }
  return true;
}

bool AdvertisingManagerInterfaceHandler::ConstructData(
    const AdvertisementProperties& properties,
    std::vector<uint8_t>* data,
    brillo::ErrorPtr* error) {
  return AddType(properties.type.value(), data, error) &&
         AddIncludeTxPower(properties.include_tx_power.value(), data, error) &&
         AddServiceUuid(properties.service_uuids.value(), data, error) &&
         AddSolicitUuid(properties.solicit_uuids.value(), data, error) &&
         AddServiceData(properties.service_data.value(), data, error) &&
         AddManufacturerData(properties.manufacturer_data.value(), data, error);
}

bool AdvertisingManagerInterfaceHandler::ConfigureData(
    hci_adv_set_t handle,
    const std::vector<uint8_t>& data,
    brillo::ErrorPtr* error) {
  if (!libnewblue_->HciAdvSetConfigureData(handle, false, data.data(),
                                           data.size())) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorFailed,
                         "Cannot configure data");
    return false;
  }

  return true;
}

bool AdvertisingManagerInterfaceHandler::SetParams(hci_adv_set_t handle,
                                                   brillo::ErrorPtr* error) {
  // Some chips can only support HCI_ADV_TYPE_ADV_IND.
  if (!libnewblue_->HciAdvSetSetAdvParams(
          handle, /* min_interval = */ 0x0040, /* max_interval = */ 0x0100,
          HCI_ADV_TYPE_ADV_IND, HCI_ADV_OWN_ADDR_TYPE_PUBLIC,
          /* address = */ nullptr,
          HCI_ADV_CHAN_MAP_USE_CHAN_37 | HCI_ADV_CHAN_MAP_USE_CHAN_38 |
              HCI_ADV_CHAN_MAP_USE_CHAN_39,
          HCI_ADV_FILTER_POL_SCAN_ALL_CONNECT_ALL,
          HCI_ADV_TX_PWR_LVL_DONT_CARE)) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorFailed,
                         "Cannot set parameters");
    return false;
  }

  return true;
}

bool AdvertisingManagerInterfaceHandler::Enable(hci_adv_set_t handle,
                                                brillo::ErrorPtr* error) {
  if (!libnewblue_->HciAdvSetEnable(handle)) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
                         bluetooth_advertising_manager::kErrorFailed,
                         "Cannot enable advertisement");
    return false;
  }

  return true;
}

}  // namespace bluetooth
