// Copyright 2018 The Fuchsia 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 "host_server.h"

#include <zircon/assert.h>

#include "garnet/drivers/bluetooth/host/gatt_host.h"
#include "garnet/drivers/bluetooth/lib/common/log.h"
#include "garnet/drivers/bluetooth/lib/gap/adapter.h"
#include "garnet/drivers/bluetooth/lib/gap/bredr_connection_manager.h"
#include "garnet/drivers/bluetooth/lib/gap/bredr_discovery_manager.h"
#include "garnet/drivers/bluetooth/lib/gap/gap.h"
#include "garnet/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h"
#include "garnet/drivers/bluetooth/lib/sm/util.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_number_conversions.h"
#include "lib/fxl/strings/string_printf.h"

#include "helpers.h"
#include "low_energy_central_server.h"
#include "low_energy_peripheral_server.h"
#include "profile_server.h"

namespace bthost {

using btlib::sm::IOCapability;
using fidl_helpers::NewFidlError;
using fuchsia::bluetooth::Bool;
using fuchsia::bluetooth::ErrorCode;
using fuchsia::bluetooth::Status;
using fuchsia::bluetooth::control::AdapterState;
using fuchsia::bluetooth::control::RemoteDevice;
using fuchsia::bluetooth::host::BondingData;

HostServer::HostServer(zx::channel channel,
                       fxl::WeakPtr<::btlib::gap::Adapter> adapter,
                       fbl::RefPtr<GattHost> gatt_host)
    : AdapterServerBase(adapter, this, std::move(channel)),
      pairing_delegate_(nullptr),
      gatt_host_(gatt_host),
      requesting_discovery_(false),
      requesting_discoverable_(false),
      io_capability_(IOCapability::kNoInputNoOutput),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(gatt_host_);

  auto self = weak_ptr_factory_.GetWeakPtr();
  adapter->remote_device_cache()->set_device_updated_callback(
      [self](const auto& device) {
        if (self) {
          self->OnRemoteDeviceUpdated(device);
        }
      });
  adapter->remote_device_cache()->set_device_removed_callback(
      [self](const auto& identifier) {
        if (self) {
          self->OnRemoteDeviceRemoved(identifier);
        }
      });
  adapter->remote_device_cache()->set_device_bonded_callback(
      [self](const auto& device) {
        if (self) {
          self->OnRemoteDeviceBonded(device);
        }
      });
  adapter->set_auto_connect_callback([self](auto conn_ref) {
    if (self) {
      self->OnConnect(std::move(conn_ref), true);
    }
  });
}

HostServer::~HostServer() { Close(); }

void HostServer::GetInfo(GetInfoCallback callback) {
  callback(fidl_helpers::NewAdapterInfo(*adapter()));
}

void HostServer::ListDevices(ListDevicesCallback callback) {
  std::vector<RemoteDevice> fidl_devices;
  adapter()->remote_device_cache()->ForEach(
      [&fidl_devices](const btlib::gap::RemoteDevice& dev) {
        if (dev.connectable()) {
          fidl_devices.push_back(fidl_helpers::NewRemoteDevice(dev));
        }
      });
  callback(std::vector<RemoteDevice>(std::move(fidl_devices)));
}

void HostServer::SetLocalName(::std::string local_name,
                              SetLocalNameCallback callback) {
  ZX_DEBUG_ASSERT(!local_name.empty());
  // Make a copy of |local_name| to move separately into the lambda.
  std::string name_copy(local_name);
  adapter()->SetLocalName(
      std::move(local_name),
      [self = weak_ptr_factory_.GetWeakPtr(), local_name = std::move(name_copy),
       callback = std::move(callback)](auto status) {
        // Send adapter state update on success and if the connection is still
        // open.
        if (status && self) {
          AdapterState state;
          state.local_name = std::move(local_name);
          self->binding()->events().OnAdapterStateChanged(std::move(state));
        }
        callback(fidl_helpers::StatusToFidl(status, "Can't Set Local Name"));
      });
}

void HostServer::StartLEDiscovery(StartDiscoveryCallback callback) {
  auto le_manager = adapter()->le_discovery_manager();
  if (!le_manager) {
    callback(fidl_helpers::NewFidlError(ErrorCode::BAD_STATE,
                                        "Adapter is not initialized yet."));
    return;
  }
  le_manager->StartDiscovery([self = weak_ptr_factory_.GetWeakPtr(),
                              callback = std::move(callback)](auto session) {
    // End the new session if this AdapterServer got destroyed in the
    // mean time (e.g. because the client disconnected).
    if (!self) {
      callback(
          fidl_helpers::NewFidlError(ErrorCode::FAILED, "Adapter Shutdown"));
      return;
    }

    if (!self->requesting_discovery_) {
      callback(
          fidl_helpers::NewFidlError(ErrorCode::CANCELED, "Request canceled"));
      return;
    }

    if (!session) {
      bt_log(TRACE, "bt-host", "failed to start LE discovery session");
      callback(fidl_helpers::NewFidlError(
          ErrorCode::FAILED, "Failed to start LE discovery session"));
      self->bredr_discovery_session_ = nullptr;
      self->requesting_discovery_ = false;
      return;
    }

    // Set up a general-discovery filter for connectable devices.
    // NOTE(armansito): This currently has no effect since OnDeviceUpdated
    // events are generated based on RemoteDeviceCache events. |session|'s
    // "result callback" is unused.
    session->filter()->set_connectable(true);
    session->filter()->SetGeneralDiscoveryFlags();

    self->le_discovery_session_ = std::move(session);
    self->requesting_discovery_ = false;

    // Send the adapter state update.
    AdapterState state;
    state.discovering = Bool::New();
    state.discovering->value = true;
    self->binding()->events().OnAdapterStateChanged(std::move(state));

    callback(Status());
  });
}

void HostServer::StartDiscovery(StartDiscoveryCallback callback) {
  bt_log(TRACE, "bt-host", "StartDiscovery()");
  ZX_DEBUG_ASSERT(adapter());

  if (le_discovery_session_ || requesting_discovery_) {
    bt_log(TRACE, "bt-host", "discovery already in progress");
    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
                                        "Discovery already in progress"));
    return;
  }

  requesting_discovery_ = true;
  auto bredr_manager = adapter()->bredr_discovery_manager();
  if (!bredr_manager) {
    StartLEDiscovery(std::move(callback));
    return;
  }
  // TODO(jamuraa): start these in parallel instead of sequence
  bredr_manager->RequestDiscovery(
      [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback)](
          btlib::hci::Status status, auto session) mutable {
        if (!self) {
          callback(fidl_helpers::NewFidlError(ErrorCode::FAILED,
                                              "Adapter Shutdown"));
          return;
        }

        if (!self->requesting_discovery_) {
          callback(fidl_helpers::NewFidlError(ErrorCode::CANCELED,
                                              "Request Canceled"));
          return;
        }

        if (!status || !session) {
          bt_log(TRACE, "bt-host", "failed to start BR/EDR discovery session");
          callback(fidl_helpers::StatusToFidl(
              status, "Failed to start BR/EDR discovery session"));
          self->requesting_discovery_ = false;
          return;
        }

        self->bredr_discovery_session_ = std::move(session);
        self->StartLEDiscovery(std::move(callback));
      });
}

void HostServer::StopDiscovery(StopDiscoveryCallback callback) {
  bt_log(TRACE, "bt-host", "StopDiscovery()");
  if (!le_discovery_session_) {
    bt_log(TRACE, "bt-host", "no active discovery session");
    callback(fidl_helpers::NewFidlError(ErrorCode::BAD_STATE,
                                        "No discovery session in progress"));
    return;
  }

  bredr_discovery_session_ = nullptr;
  le_discovery_session_ = nullptr;

  AdapterState state;
  state.discovering = Bool::New();
  state.discovering->value = false;
  this->binding()->events().OnAdapterStateChanged(std::move(state));

  callback(Status());
}

void HostServer::SetConnectable(bool connectable,
                                SetConnectableCallback callback) {
  bt_log(TRACE, "bt-host", "SetConnectable(%s)",
         connectable ? "true" : "false");

  auto bredr_conn_manager = adapter()->bredr_connection_manager();
  if (!bredr_conn_manager) {
    callback(fidl_helpers::NewFidlError(ErrorCode::NOT_SUPPORTED,
                                        "Connectable mode not available"));
    return;
  }
  bredr_conn_manager->SetConnectable(
      connectable, [callback = std::move(callback)](const auto& status) {
        callback(fidl_helpers::StatusToFidl(status));
      });
}

void HostServer::AddBondedDevices(::std::vector<BondingData> bonds,
                                  AddBondedDevicesCallback callback) {
  bt_log(TRACE, "bt-host", "AddBondedDevices");
  if (bonds.empty()) {
    callback(fidl_helpers::NewFidlError(ErrorCode::NOT_SUPPORTED,
                                        "No bonds were added"));
    return;
  }

  for (auto& bond : bonds) {
    btlib::sm::PairingData bond_data;
    if (bond.le) {
      bond_data = fidl_helpers::PairingDataFromFidl(*bond.le);

      // Report error if bond data is missing a security key.
      if (!bond_data.irk && !bond_data.csrk) {
        bt_log(ERROR, "bt-host", "LE bond data is missing security key");
        callback(fidl_helpers::NewFidlError(ErrorCode::INVALID_ARGUMENTS,
                                            "LE IRK/CSRK missing"));
        return;
      }
    }

    // TODO(armansito): Handle BR/EDR data here. For now we skip the entry if LE
    // data isn't available.
    if (!bond_data.identity_address) {
      bt_log(ERROR, "bt-host", "LE bonding data is required");
      continue;
    }

    // TODO(armansito): BondingData should contain the identity address for both
    // transports instead of storing them separately. For now use the one we
    // obtained from |bond.le|.
    if (!adapter()->AddBondedDevice(bond.identifier,
                                    *bond_data.identity_address, bond_data)) {
      // TODO(armansito): Continue walking the list if this fails?
      callback(fidl_helpers::NewFidlError(
          ErrorCode::FAILED,
          fxl::StringPrintf("Failed to initialize bonded device (id: %s)",
                            bond.identifier.c_str())));
      return;
    }
  }

  callback(Status());
}

void HostServer::OnRemoteDeviceBonded(
    const ::btlib::gap::RemoteDevice& remote_device) {
  bt_log(TRACE, "bt-host", "OnRemoteDeviceBonded()");
  binding()->events().OnNewBondingData(
      fidl_helpers::NewBondingData(*adapter(), remote_device));
}

void HostServer::OnConnect(btlib::gap::LowEnergyConnectionRefPtr conn_ref,
                           bool auto_connect) {
  ZX_DEBUG_ASSERT(conn_ref);

  const auto& id = conn_ref->device_identifier();
  auto iter = le_connections_.find(id);
  if (iter != le_connections_.end()) {
    bt_log(WARN, "bt-host", "%s device already connected; reference dropped",
           (auto_connect ? "auto-connected" : "manually-connected"));
    return;
  }

  bt_log(TRACE, "bt-host", "LE device %s: %s ",
         (auto_connect ? "auto-connected" : "manually_connected"), id.c_str());
  conn_ref->set_closed_callback([self = weak_ptr_factory_.GetWeakPtr(), id] {
    if (self)
      self->le_connections_.erase(id);
  });
  le_connections_[id] = std::move(conn_ref);
}

void HostServer::SetDiscoverable(bool discoverable,
                                 SetDiscoverableCallback callback) {
  bt_log(TRACE, "bt-host", "SetDiscoverable(%s)",
         discoverable ? "true" : "false");
  // TODO(NET-830): advertise LE here
  if (!discoverable) {
    bredr_discoverable_session_ = nullptr;

    AdapterState state;
    state.discoverable = Bool::New();
    state.discoverable->value = false;
    this->binding()->events().OnAdapterStateChanged(std::move(state));

    callback(Status());
    return;
  }
  if (discoverable && requesting_discoverable_) {
    bt_log(TRACE, "bt-host", "SetDiscoverable already in progress");
    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
                                        "SetDiscoverable already in progress"));
    return;
  }
  requesting_discoverable_ = true;
  auto bredr_manager = adapter()->bredr_discovery_manager();
  if (!bredr_manager) {
    callback(fidl_helpers::NewFidlError(ErrorCode::FAILED,
                                        "Discoverable mode not available"));
    return;
  }
  bredr_manager->RequestDiscoverable(
      [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback)](
          btlib::hci::Status status, auto session) {
        if (!self) {
          callback(fidl_helpers::NewFidlError(ErrorCode::FAILED,
                                              "Adapter Shutdown"));
          return;
        }

        if (!self->requesting_discoverable_) {
          callback(fidl_helpers::NewFidlError(ErrorCode::CANCELED,
                                              "Request canceled"));
          return;
        }

        if (!status || !session) {
          bt_log(TRACE, "bt-host", "failed to set discoverable");
          callback(
              fidl_helpers::StatusToFidl(status, "Failed to set discoverable"));
          self->requesting_discoverable_ = false;
          return;
        }

        self->bredr_discoverable_session_ = std::move(session);
        self->requesting_discoverable_ = false;
        AdapterState state;
        state.discoverable = Bool::New();
        state.discoverable->value = true;
        self->binding()->events().OnAdapterStateChanged(std::move(state));
        callback(Status());
      });
}

void HostServer::EnableBackgroundScan(bool enabled) {
  bt_log(TRACE, "bt-host", "%s background scan",
         (enabled ? "enabled" : "disable"));
  auto le_manager = adapter()->le_discovery_manager();
  if (le_manager) {
    le_manager->EnableBackgroundScan(enabled);
  }
}

void HostServer::SetPairingDelegate(
    ::fuchsia::bluetooth::control::InputCapabilityType input,
    ::fuchsia::bluetooth::control::OutputCapabilityType output,
    ::fidl::InterfaceHandle<::fuchsia::bluetooth::control::PairingDelegate>
        delegate) {
  bool cleared = !delegate;
  pairing_delegate_.Bind(std::move(delegate));

  if (cleared) {
    bt_log(TRACE, "bt-host", "PairingDelegate cleared");
    ResetPairingDelegate();
    return;
  }

  io_capability_ = fidl_helpers::IoCapabilityFromFidl(input, output);
  bt_log(TRACE, "bt-host", "PairingDelegate assigned (I/O capability: %s)",
         btlib::sm::util::IOCapabilityToString(io_capability_).c_str());

  auto self = weak_ptr_factory_.GetWeakPtr();
  adapter()->SetPairingDelegate(self);
  pairing_delegate_.set_error_handler([self](zx_status_t status) {
    bt_log(TRACE, "bt-host", "PairingDelegate disconnected");
    if (self) {
      self->ResetPairingDelegate();
    }
  });
}

void HostServer::Connect(::std::string device_id,
                         ConnectCallback callback) {
  auto device = adapter()->remote_device_cache()->FindDeviceById(device_id);
  if (!device) {
    // We don't support connections to devices not in our cache
    callback(NewFidlError(ErrorCode::NOT_FOUND,
                          "Cannot find device with the given ID"));
    return;
  }

  if (!device->le()) {
    // TODO(NET-411): implement BR/EDR connect
    // TODO(NET-411): If a dual-mode device, we attempt to connect both
    // protocols, and if either fails, close the other and return failure
    callback(
        NewFidlError(ErrorCode::NOT_SUPPORTED,
                     "Device does not support LowEnergy connections, and "
                     "outgoing Classic connections are not yet supported"));
    return;
  }

  // TODO(NET-411): Once dual-mode is supported, this logic will vary depending
  // on whether we are initiating a BR/EDR connection as well. We may want to
  // refactor this into a separate ConnectLowEnergy method.
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto on_complete = [self, callback = std::move(callback),
                      peer_id = device_id](auto status, auto conn_ref) {
    if (!status) {
      ZX_DEBUG_ASSERT(!conn_ref);
      bt_log(TRACE, "bt-host", "failed to connect to connect to device (id %s)",
             peer_id.c_str());
      callback(fidl_helpers::StatusToFidl(status, "failed to connect"));
    } else {
      ZX_DEBUG_ASSERT(conn_ref);
      ZX_DEBUG_ASSERT(peer_id == conn_ref->device_identifier());
      callback(Status());
    }
    if (self) {
      self->OnConnect(std::move(conn_ref), false);
    }
  };
  adapter()->le_connection_manager()->Connect(device_id,
                                              std::move(on_complete));
}

void HostServer::RequestLowEnergyCentral(
    fidl::InterfaceRequest<fuchsia::bluetooth::le::Central> request) {
  BindServer<LowEnergyCentralServer>(std::move(request), gatt_host_);
}

void HostServer::RequestLowEnergyPeripheral(
    fidl::InterfaceRequest<fuchsia::bluetooth::le::Peripheral> request) {
  BindServer<LowEnergyPeripheralServer>(std::move(request));
}

void HostServer::RequestGattServer(
    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request) {
  // GATT FIDL requests are handled by GattHost.
  gatt_host_->BindGattServer(std::move(request));
}

void HostServer::RequestProfile(
    fidl::InterfaceRequest<fuchsia::bluetooth::bredr::Profile> request) {
  BindServer<ProfileServer>(std::move(request));
}

void HostServer::Close() {
  bt_log(TRACE, "bt-host", "closing FIDL handles");

  // Invalidate all weak pointers. This will guarantee that all pending tasks
  // that reference this HostServer will return early if they run in the future.
  weak_ptr_factory_.InvalidateWeakPtrs();

  // Destroy all FIDL bindings.
  servers_.clear();
  gatt_host_->CloseServers();

  // Cancel pending requests.
  requesting_discovery_ = false;
  requesting_discoverable_ = false;

  // Diff for final adapter state update.
  bool send_update = false;
  AdapterState state;

  // Stop all procedures initiated via host.
  if (le_discovery_session_ || bredr_discovery_session_) {
    send_update = true;
    le_discovery_session_ = nullptr;
    bredr_discovery_session_ = nullptr;

    state.discovering = Bool::New();
    state.discovering->value = false;
  }

  if (bredr_discoverable_session_) {
    send_update = true;
    bredr_discoverable_session_ = nullptr;

    state.discoverable = Bool::New();
    state.discoverable->value = false;
  }

  // Drop all connections that are attached to this HostServer.
  le_connections_.clear();

  // Stop background scan if enabled.
  auto le_manager = adapter()->le_discovery_manager();
  if (le_manager) {
    le_manager->EnableBackgroundScan(false);
  }

  // Disallow future pairing.
  pairing_delegate_ = nullptr;
  ResetPairingDelegate();

  // Send adapter state change.
  if (send_update) {
    binding()->events().OnAdapterStateChanged(std::move(state));
  }
}

btlib::sm::IOCapability HostServer::io_capability() const {
  bt_log(TRACE, "bt-host", "I/O capability: %s",
         btlib::sm::util::IOCapabilityToString(io_capability_).c_str());
  return io_capability_;
}

void HostServer::CompletePairing(std::string id, btlib::sm::Status status) {
  bt_log(INFO, "bt-host", "pairing complete for device: %s, status: %s",
         id.c_str(), status.ToString().c_str());
  ZX_DEBUG_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingComplete(std::move(id),
                                       fidl_helpers::StatusToFidl(status));
}

void HostServer::ConfirmPairing(std::string id, ConfirmCallback confirm) {
  bt_log(INFO, "bt-host", "pairing request for device: %s", id.c_str());
  auto found_device = adapter()->remote_device_cache()->FindDeviceById(id);
  ZX_DEBUG_ASSERT(found_device);
  auto device = fidl_helpers::NewRemoteDevicePtr(*found_device);
  ZX_DEBUG_ASSERT(device);

  ZX_DEBUG_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingRequest(
      std::move(*device), fuchsia::bluetooth::control::PairingMethod::CONSENT,
      nullptr,
      [confirm = std::move(confirm)](
          const bool success, const std::string passkey) { confirm(success); });
}

void HostServer::DisplayPasskey(std::string id, uint32_t passkey,
                                ConfirmCallback confirm) {
  bt_log(INFO, "bt-host", "pairing request for device: %s", id.c_str());
  bt_log(INFO, "bt-host", "enter passkey: %06u", passkey);

  auto device = fidl_helpers::NewRemoteDevicePtr(
      *adapter()->remote_device_cache()->FindDeviceById(id));
  ZX_DEBUG_ASSERT(device);

  ZX_DEBUG_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingRequest(
      std::move(*device),
      fuchsia::bluetooth::control::PairingMethod::PASSKEY_DISPLAY,
      fxl::StringPrintf("%06u", passkey),
      [confirm = std::move(confirm)](
          const bool success, const std::string passkey) { confirm(success); });
}

void HostServer::RequestPasskey(std::string id,
                                PasskeyResponseCallback respond) {
  auto device = fidl_helpers::NewRemoteDevicePtr(
      *adapter()->remote_device_cache()->FindDeviceById(id));
  ZX_DEBUG_ASSERT(device);

  ZX_DEBUG_ASSERT(pairing_delegate_);
  pairing_delegate_->OnPairingRequest(
      std::move(*device),
      fuchsia::bluetooth::control::PairingMethod::PASSKEY_ENTRY, nullptr,
      [respond = std::move(respond)](const bool success,
                                     const std::string passkey) {
        if (!success) {
          respond(-1);
        } else {
          uint32_t response;
          if (!fxl::StringToNumberWithError<uint32_t>(passkey, &response)) {
            bt_log(ERROR, "bt-host", "Unrecognized integer in string: %s",
                   passkey.c_str());
            respond(-1);
          } else {
            respond(response);
          }
        }
      });
}

void HostServer::OnConnectionError(Server* server) {
  ZX_DEBUG_ASSERT(server);
  servers_.erase(server);
}

void HostServer::OnRemoteDeviceUpdated(
    const ::btlib::gap::RemoteDevice& remote_device) {
  if (!remote_device.connectable()) {
    return;
  }

  auto fidl_device = fidl_helpers::NewRemoteDevicePtr(remote_device);
  if (!fidl_device) {
    bt_log(TRACE, "bt-host", "ignoring malformed device update");
    return;
  }

  this->binding()->events().OnDeviceUpdated(std::move(*fidl_device));
}

void HostServer::OnRemoteDeviceRemoved(const std::string& identifier) {
  // TODO(armansito): Notify only if the device is connectable for symmetry with
  // OnDeviceUpdated?
  this->binding()->events().OnDeviceRemoved(identifier);
}

void HostServer::ResetPairingDelegate() {
  io_capability_ = IOCapability::kNoInputNoOutput;
  adapter()->SetPairingDelegate(fxl::WeakPtr<HostServer>());
}

}  // namespace bthost
