// Copyright 2014 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 "components/pairing/bluetooth_host_pairing_controller.h"

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/hash/hash.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "chromeos/constants/devicetype.h"
#include "components/pairing/bluetooth_pairing_constants.h"
#include "components/pairing/pairing_api.pb.h"
#include "components/pairing/proto_decoder.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/io_buffer.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"

namespace pairing_chromeos {

namespace {
const int kReceiveSize = 16384;

pairing_api::HostStatusParameters::Connectivity PairingApiConnectivityStatus(
    HostPairingController::Connectivity connectivity_status) {
  switch (connectivity_status) {
    case HostPairingController::CONNECTIVITY_UNTESTED:
      return pairing_api::HostStatusParameters::CONNECTIVITY_UNTESTED;
    case HostPairingController::CONNECTIVITY_NONE:
      return pairing_api::HostStatusParameters::CONNECTIVITY_NONE;
    case HostPairingController::CONNECTIVITY_LIMITED:
      return pairing_api::HostStatusParameters::CONNECTIVITY_LIMITED;
    case HostPairingController::CONNECTIVITY_CONNECTING:
      return pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTING;
    case HostPairingController::CONNECTIVITY_CONNECTED:
      return pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTED;
    default:
      NOTREACHED();
      return pairing_api::HostStatusParameters::CONNECTIVITY_UNTESTED;
  }
}

pairing_api::HostStatusParameters::UpdateStatus PairingApiUpdateStatus(
    HostPairingController::UpdateStatus update_status) {
  switch(update_status) {
    case HostPairingController::UPDATE_STATUS_UNKNOWN:
      return pairing_api::HostStatusParameters::UPDATE_STATUS_UNKNOWN;
    case HostPairingController::UPDATE_STATUS_UPDATING:
      return pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATING;
    case HostPairingController::UPDATE_STATUS_REBOOTING:
      return pairing_api::HostStatusParameters::UPDATE_STATUS_REBOOTING;
    case HostPairingController::UPDATE_STATUS_UPDATED:
      return pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED;
    default:
      NOTREACHED();
      return pairing_api::HostStatusParameters::UPDATE_STATUS_UNKNOWN;
  }
}

pairing_api::HostStatusParameters::EnrollmentStatus PairingApiEnrollmentStatus(
    HostPairingController::EnrollmentStatus enrollment_status) {
  switch(enrollment_status) {
    case HostPairingController::ENROLLMENT_STATUS_UNKNOWN:
      return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_UNKNOWN;
    case HostPairingController::ENROLLMENT_STATUS_ENROLLING:
      return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_ENROLLING;
    case HostPairingController::ENROLLMENT_STATUS_FAILURE:
      return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_FAILURE;
    case HostPairingController::ENROLLMENT_STATUS_SUCCESS:
      return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_SUCCESS;
    default:
      NOTREACHED();
      return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_UNKNOWN;
  }
}

}  // namespace

BluetoothHostPairingController::BluetoothHostPairingController(
    service_manager::Connector* connector)
    : proto_decoder_(std::make_unique<ProtoDecoder>(this)) {
  DCHECK(connector);
  connector->BindInterface(device::mojom::kServiceName,
                           mojo::MakeRequest(&input_device_manager_));
}

BluetoothHostPairingController::~BluetoothHostPairingController() {
  Reset();
}

void BluetoothHostPairingController::SetDelegateForTesting(
    TestDelegate* delegate) {
  delegate_ = delegate;
}

scoped_refptr<device::BluetoothAdapter>
BluetoothHostPairingController::GetAdapterForTesting() {
  return adapter_;
}

void BluetoothHostPairingController::ChangeStage(Stage new_stage) {
  if (current_stage_ == new_stage)
    return;
  VLOG(1) << "ChangeStage " << new_stage;
  current_stage_ = new_stage;
  for (Observer& observer : observers_)
    observer.PairingStageChanged(new_stage);
}

void BluetoothHostPairingController::SendHostStatus() {
  pairing_api::HostStatus host_status;

  host_status.set_api_version(kPairingAPIVersion);
  if (!enrollment_domain_.empty())
    host_status.mutable_parameters()->set_domain(enrollment_domain_);
  if (!permanent_id_.empty())
    host_status.mutable_parameters()->set_permanent_id(permanent_id_);

  // TODO(zork): Get these values from the UI. (http://crbug.com/405744)
  host_status.mutable_parameters()->set_connectivity(
      PairingApiConnectivityStatus(connectivity_status_));
  host_status.mutable_parameters()->set_update_status(
      PairingApiUpdateStatus(update_status_));
  host_status.mutable_parameters()->set_enrollment_status(
      PairingApiEnrollmentStatus(enrollment_status_));

  // TODO(zork): Get a list of other paired controllers.
  // (http://crbug.com/405757)

  int size = 0;
  scoped_refptr<net::IOBuffer> io_buffer(
      ProtoDecoder::SendHostStatus(host_status, &size));

  controller_socket_->Send(
      io_buffer, size,
      base::Bind(&BluetoothHostPairingController::OnSendComplete,
                 ptr_factory_.GetWeakPtr()),
      base::Bind(&BluetoothHostPairingController::OnSendError,
                 ptr_factory_.GetWeakPtr()));
}

void BluetoothHostPairingController::SendErrorCodeAndMessage() {
  if (error_code_ ==
      static_cast<int>(HostPairingController::ErrorCode::ERROR_NONE)) {
    return;
  }

  pairing_api::Error error_status;
  error_status.set_api_version(kPairingAPIVersion);
  error_status.mutable_parameters()->set_code(error_code_);
  error_status.mutable_parameters()->set_description(error_message_);

  int size = 0;
  scoped_refptr<net::IOBuffer> io_buffer(
      ProtoDecoder::SendError(error_status, &size));

  controller_socket_->Send(
      io_buffer, size,
      base::Bind(&BluetoothHostPairingController::OnSendComplete,
                 ptr_factory_.GetWeakPtr()),
      base::Bind(&BluetoothHostPairingController::OnSendError,
                 ptr_factory_.GetWeakPtr()));
}

void BluetoothHostPairingController::Reset() {
  if (adapter_.get()) {
    device::BluetoothDevice* device =
        adapter_->GetDevice(controller_device_address_);
    if (device && device->IsPaired()) {
      device->Forget(base::Bind(&BluetoothHostPairingController::OnForget,
                                ptr_factory_.GetWeakPtr()),
                     base::Bind(&BluetoothHostPairingController::OnForget,
                                ptr_factory_.GetWeakPtr()));
      return;
    }
  }
  OnForget();
}

void BluetoothHostPairingController::OnGetAdapter(
    scoped_refptr<device::BluetoothAdapter> adapter) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!adapter_.get());
  adapter_ = adapter;

  if (adapter_->IsPresent()) {
    SetPowered();
  } else {
    // Set the name once the adapter is present.
    adapter_->AddObserver(this);
  }
}

void BluetoothHostPairingController::SetPowered() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (adapter_->IsPowered()) {
    was_powered_ = true;
    OnSetPowered();
  } else {
    adapter_->SetPowered(
        true,
        base::Bind(&BluetoothHostPairingController::OnSetPowered,
                   ptr_factory_.GetWeakPtr()),
        base::Bind(&BluetoothHostPairingController::OnSetError,
                   ptr_factory_.GetWeakPtr()));
  }
}

void BluetoothHostPairingController::OnSetPowered() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  adapter_->AddPairingDelegate(
      this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);

  device::BluetoothAdapter::ServiceOptions options;
  options.name.reset(new std::string(kPairingServiceName));

  adapter_->CreateRfcommService(
      device::BluetoothUUID(kPairingServiceUUID), options,
      base::Bind(&BluetoothHostPairingController::OnCreateService,
                 ptr_factory_.GetWeakPtr()),
      base::Bind(&BluetoothHostPairingController::OnCreateServiceError,
                 ptr_factory_.GetWeakPtr()));
}

void BluetoothHostPairingController::OnCreateService(
    scoped_refptr<device::BluetoothSocket> socket) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  service_socket_ = socket;

  service_socket_->Accept(
      base::Bind(&BluetoothHostPairingController::OnAccept,
                 ptr_factory_.GetWeakPtr()),
      base::Bind(&BluetoothHostPairingController::OnAcceptError,
                 ptr_factory_.GetWeakPtr()));

  adapter_->SetDiscoverable(
      true,
      base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
                 ptr_factory_.GetWeakPtr(), true),
      base::Bind(&BluetoothHostPairingController::OnSetError,
                 ptr_factory_.GetWeakPtr()));
}

void BluetoothHostPairingController::OnAccept(
    const device::BluetoothDevice* device,
    scoped_refptr<device::BluetoothSocket> socket) {
  controller_device_address_ = device->GetAddress();

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  adapter_->SetDiscoverable(
      false,
      base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
                 ptr_factory_.GetWeakPtr(), false),
      base::Bind(&BluetoothHostPairingController::OnSetError,
                 ptr_factory_.GetWeakPtr()));
  controller_socket_ = socket;

  SendHostStatus();

  controller_socket_->Receive(
      kReceiveSize,
      base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
                 ptr_factory_.GetWeakPtr()),
      base::Bind(&BluetoothHostPairingController::OnReceiveError,
                 ptr_factory_.GetWeakPtr()));
}

void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (change_stage) {
    DCHECK_EQ(current_stage_, STAGE_NONE);
    ChangeStage(STAGE_WAITING_FOR_CONTROLLER);
  }
}

void BluetoothHostPairingController::OnSendComplete(int bytes_sent) {}

void BluetoothHostPairingController::OnReceiveComplete(
    int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  proto_decoder_->DecodeIOBuffer(bytes, io_buffer);

  if (controller_socket_.get()) {
    controller_socket_->Receive(
        kReceiveSize,
        base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
                   ptr_factory_.GetWeakPtr()),
        base::Bind(&BluetoothHostPairingController::OnReceiveError,
                   ptr_factory_.GetWeakPtr()));
  }
}

void BluetoothHostPairingController::OnCreateServiceError(
    const std::string& message) {
  LOG(ERROR) << message;
  ChangeStage(STAGE_INITIALIZATION_ERROR);
}

void BluetoothHostPairingController::OnSetError() {
  adapter_->RemovePairingDelegate(this);
  ChangeStage(STAGE_INITIALIZATION_ERROR);
}

void BluetoothHostPairingController::OnAcceptError(
    const std::string& error_message) {
  LOG(ERROR) << error_message;
  ChangeStage(STAGE_CONTROLLER_CONNECTION_ERROR);
}

void BluetoothHostPairingController::OnSendError(
    const std::string& error_message) {
  LOG(ERROR) << error_message;
  if (enrollment_status_ != ENROLLMENT_STATUS_ENROLLING &&
      enrollment_status_ != ENROLLMENT_STATUS_SUCCESS) {
    ChangeStage(STAGE_CONTROLLER_CONNECTION_ERROR);
  }
}

void BluetoothHostPairingController::PowerOffAdapterIfApplicable(
    std::vector<InputDeviceInfoPtr> devices) {
  bool use_bluetooth = false;
  for (auto& device : devices) {
    if (device->type == device::mojom::InputDeviceType::TYPE_BLUETOOTH) {
      use_bluetooth = true;
      break;
    }
  }
  if (!was_powered_ && !use_bluetooth) {
    adapter_->SetPowered(
        false, base::Bind(&BluetoothHostPairingController::ResetAdapter,
                          ptr_factory_.GetWeakPtr()),
        base::Bind(&BluetoothHostPairingController::ResetAdapter,
                   ptr_factory_.GetWeakPtr()));
  } else {
    ResetAdapter();
  }
}

void BluetoothHostPairingController::ResetAdapter() {
  adapter_->RemoveObserver(this);
  adapter_ = nullptr;
  if (delegate_)
    delegate_->OnAdapterReset();
}

void BluetoothHostPairingController::OnForget() {
  if (controller_socket_.get()) {
    controller_socket_->Close();
    controller_socket_ = nullptr;
  }

  if (service_socket_.get()) {
    service_socket_->Close();
    service_socket_ = nullptr;
  }

  if (adapter_.get()) {
    if (adapter_->IsDiscoverable()) {
      adapter_->SetDiscoverable(false, base::DoNothing(), base::DoNothing());
    }

    input_device_manager_->GetDevices(base::BindOnce(
        &BluetoothHostPairingController::PowerOffAdapterIfApplicable,
        ptr_factory_.GetWeakPtr()));
  }
  ChangeStage(STAGE_NONE);
}

void BluetoothHostPairingController::SetControllerDeviceAddressForTesting(
    const std::string& address) {
  controller_device_address_ = address;
}

void BluetoothHostPairingController::OnReceiveError(
    device::BluetoothSocket::ErrorReason reason,
    const std::string& error_message) {
  LOG(ERROR) << reason << ", " << error_message;
  ChangeStage(STAGE_CONTROLLER_CONNECTION_ERROR);
}

void BluetoothHostPairingController::OnHostStatusMessage(
    const pairing_api::HostStatus& message) {
  NOTREACHED();
}

void BluetoothHostPairingController::OnConfigureHostMessage(
    const pairing_api::ConfigureHost& message) {
  ChangeStage(STAGE_SETUP_BASIC_CONFIGURATION);
  for (Observer& observer : observers_) {
    observer.ConfigureHostRequested(
        message.parameters().accepted_eula(), message.parameters().lang(),
        message.parameters().timezone(), message.parameters().send_reports(),
        message.parameters().keyboard_layout());
  }
}

void BluetoothHostPairingController::OnPairDevicesMessage(
    const pairing_api::PairDevices& message) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  enrollment_domain_ = message.parameters().enrolling_domain();
  ChangeStage(STAGE_ENROLLING);
  for (Observer& observer : observers_)
    observer.EnrollHostRequested(message.parameters().admin_access_token());
}

void BluetoothHostPairingController::OnCompleteSetupMessage(
    const pairing_api::CompleteSetup& message) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (current_stage_ != STAGE_ENROLLMENT_SUCCESS) {
    ChangeStage(STAGE_ENROLLMENT_ERROR);
  } else {
    // TODO(zork): Handle adding another controller. (http://crbug.com/405757)
    ChangeStage(STAGE_FINISHED);
  }
  Reset();
}

void BluetoothHostPairingController::OnErrorMessage(
    const pairing_api::Error& message) {
  NOTREACHED();
}

void BluetoothHostPairingController::OnRebootMessage(
    const pairing_api::Reboot& message) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  for (Observer& observer : observers_)
    observer.RebootHostRequested();
}

void BluetoothHostPairingController::OnAddNetworkMessage(
    const pairing_api::AddNetwork& message) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  for (Observer& observer : observers_)
    observer.AddNetworkRequested(message.parameters().onc_spec());
}

void BluetoothHostPairingController::AdapterPresentChanged(
    device::BluetoothAdapter* adapter,
    bool present) {
  DCHECK_EQ(adapter, adapter_.get());
  if (present) {
    adapter_->RemoveObserver(this);
    SetPowered();
  }
}

void BluetoothHostPairingController::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void BluetoothHostPairingController::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

HostPairingController::Stage BluetoothHostPairingController::GetCurrentStage() {
  return current_stage_;
}

void BluetoothHostPairingController::StartPairing() {
  DCHECK_EQ(current_stage_, STAGE_NONE);
  const bool bluetooth_supported =
      device::BluetoothAdapterFactory::IsBluetoothSupported();
  if (!bluetooth_supported) {
    ChangeStage(STAGE_INITIALIZATION_ERROR);
    return;
  }

  device::BluetoothAdapterFactory::GetAdapter(
      base::BindOnce(&BluetoothHostPairingController::OnGetAdapter,
                     ptr_factory_.GetWeakPtr()));
}

std::string BluetoothHostPairingController::GetDeviceName() {
  return adapter_.get() ? adapter_->GetName() : std::string();
}

std::string BluetoothHostPairingController::GetConfirmationCode() {
  DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
  return confirmation_code_;
}

std::string BluetoothHostPairingController::GetEnrollmentDomain() {
  return enrollment_domain_;
}

void BluetoothHostPairingController::OnNetworkConnectivityChanged(
    Connectivity connectivity_status) {
  connectivity_status_ = connectivity_status;
  if (connectivity_status == CONNECTIVITY_NONE) {
    ChangeStage(STAGE_SETUP_NETWORK_ERROR);
    SendErrorCodeAndMessage();
  } else {
    SendHostStatus();
  }
}

void BluetoothHostPairingController::OnUpdateStatusChanged(
    UpdateStatus update_status) {
  update_status_ = update_status;
  if (update_status == UPDATE_STATUS_UPDATED)
    ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
  SendHostStatus();
}

void BluetoothHostPairingController::OnEnrollmentStatusChanged(
    EnrollmentStatus enrollment_status) {
  DCHECK_EQ(current_stage_, STAGE_ENROLLING);
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  enrollment_status_ = enrollment_status;
  if (enrollment_status == ENROLLMENT_STATUS_SUCCESS) {
    ChangeStage(STAGE_ENROLLMENT_SUCCESS);
    SendHostStatus();
  } else if (enrollment_status == ENROLLMENT_STATUS_FAILURE) {
    ChangeStage(STAGE_ENROLLMENT_ERROR);
    SendErrorCodeAndMessage();
  }
}

void BluetoothHostPairingController::SetPermanentId(
    const std::string& permanent_id) {
  permanent_id_ = permanent_id;
}

void BluetoothHostPairingController::SetErrorCodeAndMessage(
    int error_code,
    const std::string& error_message) {
  error_code_ = error_code;
  error_message_ = error_message;
}

void BluetoothHostPairingController::RequestPinCode(
    device::BluetoothDevice* device) {
  // Disallow unknown device.
  device->RejectPairing();
}

void BluetoothHostPairingController::RequestPasskey(
    device::BluetoothDevice* device) {
  // Disallow unknown device.
  device->RejectPairing();
}

void BluetoothHostPairingController::DisplayPinCode(
    device::BluetoothDevice* device,
    const std::string& pincode) {
  // Disallow unknown device.
  device->RejectPairing();
}

void BluetoothHostPairingController::DisplayPasskey(
    device::BluetoothDevice* device,
    uint32_t passkey) {
  // Disallow unknown device.
  device->RejectPairing();
}

void BluetoothHostPairingController::KeysEntered(
    device::BluetoothDevice* device,
    uint32_t entered) {
  // Disallow unknown device.
  device->RejectPairing();
}

void BluetoothHostPairingController::ConfirmPasskey(
    device::BluetoothDevice* device,
    uint32_t passkey) {
  // If a new connection is occurring, reset the stage.  This can occur if the
  // pairing times out, or a new controller connects.
  if (current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION)
    ChangeStage(STAGE_WAITING_FOR_CONTROLLER);

  confirmation_code_ = base::StringPrintf("%06d", passkey);
  device->ConfirmPairing();
  ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
}

void BluetoothHostPairingController::AuthorizePairing(
    device::BluetoothDevice* device) {
  // Disallow unknown device.
  device->RejectPairing();
}

}  // namespace pairing_chromeos
