// 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 "gatt_client_server.h"

#include <lib/fit/defer.h>

#include "gatt_remote_service_server.h"
#include "helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt.h"

using fuchsia::bluetooth::ErrorCode;
using fuchsia::bluetooth::Status;

using fuchsia::bluetooth::gatt::Client;
using fuchsia::bluetooth::gatt::RemoteService;
using fuchsia::bluetooth::gatt::ServiceInfo;
using fuchsia::bluetooth::gatt::ServiceInfoPtr;

namespace bthost {

GattClientServer::GattClientServer(bt::gatt::PeerId peer_id, fbl::RefPtr<bt::gatt::GATT> gatt,
                                   fidl::InterfaceRequest<Client> request)
    : GattServerBase(gatt, this, std::move(request)), peer_id_(peer_id), weak_ptr_factory_(this) {}

void GattClientServer::ListServices(::fidl::VectorPtr<::std::string> fidl_uuids,
                                    ListServicesCallback callback) {
  // Parse the UUID list.
  std::vector<bt::UUID> uuids;
  if (fidl_uuids.has_value()) {
    // Allocate all at once and convert in-place.
    uuids.resize(fidl_uuids->size());
    for (size_t i = 0; i < uuids.size(); ++i) {
      if (!StringToUuid(fidl_uuids.value()[i], &uuids[i])) {
        callback(fidl_helpers::NewFidlError(ErrorCode::INVALID_ARGUMENTS,
                                            "Invalid UUID: " + fidl_uuids.value()[i]),
                 std::vector<ServiceInfo>((size_t)0u));
        return;
      }
    }
  }

  auto cb = [callback = std::move(callback)](bt::att::Status status, auto services) {
    std::vector<ServiceInfo> out;
    if (!status) {
      auto fidl_status =
          fidl_helpers::StatusToFidlDeprecated(status, "Failed to discover services");
      callback(std::move(fidl_status), std::move(out));
      return;
    }

    out.resize(services.size());

    size_t i = 0;
    for (const auto& svc : services) {
      ServiceInfo service_info;
      service_info.id = svc->handle();
      service_info.primary = true;
      service_info.type = svc->uuid().ToString();
      out[i++] = std::move(service_info);
    }
    callback(Status(), std::move(out));
  };

  gatt()->ListServices(peer_id_, std::move(uuids), std::move(cb));
}

void GattClientServer::ConnectToService(uint64_t id,
                                        ::fidl::InterfaceRequest<RemoteService> service) {
  if (connected_services_.count(id)) {
    bt_log(TRACE, "bt-host", "service already requested");
    return;
  }

  // Initialize an entry so that we remember when this request is in progress.
  connected_services_[id] = nullptr;

  auto self = weak_ptr_factory_.GetWeakPtr();
  auto callback = [self, id, request = std::move(service)](auto service) mutable {
    if (!self)
      return;

    // The operation must be in progress.
    ZX_DEBUG_ASSERT(self->connected_services_.count(id));

    // Automatically called on failure.
    auto fail_cleanup = fit::defer([self, id] { self->connected_services_.erase(id); });

    if (!service) {
      bt_log(TRACE, "bt-host", "failed to connect to service");
      return;
    }

    // Clean up the server if either the peer device or the FIDL client
    // disconnects.
    auto error_cb = [self, id] {
      bt_log(TRACE, "bt-host", "service disconnected");
      if (self) {
        self->connected_services_.erase(id);
      }
    };

    if (!service->AddRemovedHandler(error_cb)) {
      bt_log(TRACE, "bt-host", "failed to assign closed handler");
      return;
    }

    fail_cleanup.cancel();

    auto server = std::make_unique<GattRemoteServiceServer>(std::move(service), self->gatt(),
                                                            std::move(request));
    server->set_error_handler([cb = std::move(error_cb)](zx_status_t status) { cb(); });

    self->connected_services_[id] = std::move(server);
  };

  gatt()->FindService(peer_id_, id, std::move(callback));
}

}  // namespace bthost
