// Copyright 2016 The Chromium 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 <utility>
#include <vector>

#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "device/bluetooth/device.h"
#include "device/bluetooth/public/mojom/gatt_result_type_converter.h"
#include "mojo/public/cpp/bindings/strong_binding.h"

namespace bluetooth {
Device::~Device() {
  adapter_->RemoveObserver(this);
}

// static
void Device::Create(scoped_refptr<device::BluetoothAdapter> adapter,
                    std::unique_ptr<device::BluetoothGattConnection> connection,
                    mojom::DeviceRequest request) {
  auto device_impl =
      base::WrapUnique(new Device(adapter, std::move(connection)));
  auto* device_ptr = device_impl.get();
  device_ptr->binding_ =
      mojo::MakeStrongBinding(std::move(device_impl), std::move(request));
}

// static
mojom::DeviceInfoPtr Device::ConstructDeviceInfoStruct(
    const device::BluetoothDevice* device) {
  mojom::DeviceInfoPtr device_info = mojom::DeviceInfo::New();

  device_info->name = device->GetName();
  device_info->name_for_display =
      base::UTF16ToUTF8(device->GetNameForDisplay());
  device_info->address = device->GetAddress();
  device_info->is_gatt_connected = device->IsGattConnected();

  if (device->GetInquiryRSSI()) {
    device_info->rssi = mojom::RSSIWrapper::New();
    device_info->rssi->value = device->GetInquiryRSSI().value();
  }

  return device_info;
}

void Device::DeviceChanged(device::BluetoothAdapter* adapter,
                           device::BluetoothDevice* device) {
  if (device->GetAddress() != GetAddress()) {
    return;
  }

  if (!device->IsGattConnected()) {
    binding_->Close();
  }
}

void Device::GattServicesDiscovered(device::BluetoothAdapter* adapter,
                                    device::BluetoothDevice* device) {
  if (device->GetAddress() != GetAddress()) {
    return;
  }

  std::vector<base::Closure> requests;
  requests.swap(pending_services_requests_);
  for (const base::Closure& request : requests) {
    request.Run();
  }
}

void Device::Disconnect() {
  binding_->Close();
}

void Device::GetInfo(GetInfoCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  std::move(callback).Run(ConstructDeviceInfoStruct(device));
}

void Device::GetServices(GetServicesCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  if (device->IsGattServicesDiscoveryComplete()) {
    GetServicesImpl(std::move(callback));
    return;
  }

  // pending_services_requests_ is owned by Device, so base::Unretained is
  // safe.
  pending_services_requests_.push_back(base::Bind(&Device::GetServicesImpl,
                                                  base::Unretained(this),
                                                  base::Passed(&callback)));
}

void Device::GetCharacteristics(const std::string& service_id,
                                GetCharacteristicsCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (service == nullptr) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  std::vector<mojom::CharacteristicInfoPtr> characteristics;

  for (const auto* characteristic : service->GetCharacteristics()) {
    mojom::CharacteristicInfoPtr characteristic_info =
        mojom::CharacteristicInfo::New();

    characteristic_info->id = characteristic->GetIdentifier();
    characteristic_info->uuid = characteristic->GetUUID();
    characteristic_info->properties = characteristic->GetProperties();

    characteristics.push_back(std::move(characteristic_info));
  }

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

void Device::ReadValueForCharacteristic(
    const std::string& service_id,
    const std::string& characteristic_id,
    ReadValueForCharacteristicCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (service == nullptr) {
    std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND,
                            base::nullopt /* value */);
    return;
  }

  device::BluetoothRemoteGattCharacteristic* characteristic =
      service->GetCharacteristic(characteristic_id);
  if (characteristic == nullptr) {
    std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND,
                            base::nullopt /* value */);
    return;
  }

  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
  characteristic->ReadRemoteCharacteristic(
      base::Bind(&Device::OnReadRemoteCharacteristic,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback),
      base::Bind(&Device::OnReadRemoteCharacteristicError,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}

void Device::WriteValueForCharacteristic(
    const std::string& service_id,
    const std::string& characteristic_id,
    const std::vector<uint8_t>& value,
    WriteValueForCharacteristicCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (service == nullptr) {
    std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND);
    return;
  }

  device::BluetoothRemoteGattCharacteristic* characteristic =
      service->GetCharacteristic(characteristic_id);
  if (characteristic == nullptr) {
    std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND);
    return;
  }

  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
  characteristic->WriteRemoteCharacteristic(
      value,
      base::Bind(&Device::OnWriteRemoteCharacteristic,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback),
      base::Bind(&Device::OnWriteRemoteCharacteristicError,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}

void Device::GetDescriptors(const std::string& service_id,
                            const std::string& characteristic_id,
                            GetDescriptorsCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  if (!device) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (!service) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  device::BluetoothRemoteGattCharacteristic* characteristic =
      service->GetCharacteristic(characteristic_id);
  if (!characteristic) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  std::vector<mojom::DescriptorInfoPtr> descriptors;

  for (const auto* descriptor : characteristic->GetDescriptors()) {
    mojom::DescriptorInfoPtr descriptor_info = mojom::DescriptorInfo::New();

    descriptor_info->id = descriptor->GetIdentifier();
    descriptor_info->uuid = descriptor->GetUUID();
    descriptor_info->last_known_value = descriptor->GetValue();

    descriptors.push_back(std::move(descriptor_info));
  }

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

void Device::ReadValueForDescriptor(const std::string& service_id,
                                    const std::string& characteristic_id,
                                    const std::string& descriptor_id,
                                    ReadValueForDescriptorCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (!service) {
    std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND,
                            base::nullopt /* value */);
    return;
  }

  device::BluetoothRemoteGattCharacteristic* characteristic =
      service->GetCharacteristic(characteristic_id);
  if (!characteristic) {
    std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND,
                            base::nullopt /* value */);
    return;
  }

  device::BluetoothRemoteGattDescriptor* descriptor =
      characteristic->GetDescriptor(descriptor_id);
  if (!descriptor) {
    std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND,
                            base::nullopt /* value */);
    return;
  }

  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
  descriptor->ReadRemoteDescriptor(
      base::Bind(&Device::OnReadRemoteDescriptor,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback),
      base::Bind(&Device::OnReadRemoteDescriptorError,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}

void Device::WriteValueForDescriptor(const std::string& service_id,
                                     const std::string& characteristic_id,
                                     const std::string& descriptor_id,
                                     const std::vector<uint8_t>& value,
                                     WriteValueForDescriptorCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  device::BluetoothRemoteGattService* service =
      device->GetGattService(service_id);
  if (!service) {
    std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND);
    return;
  }

  device::BluetoothRemoteGattCharacteristic* characteristic =
      service->GetCharacteristic(characteristic_id);
  if (!characteristic) {
    std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND);
    return;
  }

  device::BluetoothRemoteGattDescriptor* descriptor =
      characteristic->GetDescriptor(descriptor_id);
  if (!descriptor) {
    std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND);
    return;
  }

  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
  descriptor->WriteRemoteDescriptor(
      value,
      base::Bind(&Device::OnWriteRemoteDescriptor,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback),
      base::Bind(&Device::OnWriteRemoteDescriptorError,
                 weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}

Device::Device(scoped_refptr<device::BluetoothAdapter> adapter,
               std::unique_ptr<device::BluetoothGattConnection> connection)
    : adapter_(std::move(adapter)),
      connection_(std::move(connection)),
      weak_ptr_factory_(this) {
  adapter_->AddObserver(this);
}

void Device::GetServicesImpl(GetServicesCallback callback) {
  device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  DCHECK(device);

  std::vector<mojom::ServiceInfoPtr> services;

  for (const device::BluetoothRemoteGattService* service :
       device->GetGattServices()) {
    services.push_back(ConstructServiceInfoStruct(*service));
  }

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

mojom::ServiceInfoPtr Device::ConstructServiceInfoStruct(
    const device::BluetoothRemoteGattService& service) {
  mojom::ServiceInfoPtr service_info = mojom::ServiceInfo::New();

  service_info->id = service.GetIdentifier();
  service_info->uuid = service.GetUUID();
  service_info->is_primary = service.IsPrimary();

  return service_info;
}

void Device::OnReadRemoteCharacteristic(
    ReadValueForCharacteristicCallback callback,
    const std::vector<uint8_t>& value) {
  std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value));
}

void Device::OnReadRemoteCharacteristicError(
    ReadValueForCharacteristicCallback callback,
    device::BluetoothGattService::GattErrorCode error_code) {
  std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code),
                          base::nullopt /* value */);
}

void Device::OnWriteRemoteCharacteristic(
    WriteValueForCharacteristicCallback callback) {
  std::move(callback).Run(mojom::GattResult::SUCCESS);
}

void Device::OnWriteRemoteCharacteristicError(
    WriteValueForCharacteristicCallback callback,
    device::BluetoothGattService::GattErrorCode error_code) {
  std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code));
}

void Device::OnReadRemoteDescriptor(ReadValueForDescriptorCallback callback,
                                    const std::vector<uint8_t>& value) {
  std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value));
}

void Device::OnReadRemoteDescriptorError(
    ReadValueForDescriptorCallback callback,
    device::BluetoothGattService::GattErrorCode error_code) {
  std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code),
                          base::nullopt /* value */);
}

void Device::OnWriteRemoteDescriptor(WriteValueForDescriptorCallback callback) {
  std::move(callback).Run(mojom::GattResult::SUCCESS);
}

void Device::OnWriteRemoteDescriptorError(
    WriteValueForDescriptorCallback callback,
    device::BluetoothGattService::GattErrorCode error_code) {
  std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code));
}

const std::string& Device::GetAddress() {
  return connection_->GetDeviceAddress();
}

}  // namespace bluetooth
