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

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

namespace bt::gatt::internal {

RemoteServiceManager::ServiceListRequest::ServiceListRequest(ServiceListCallback callback,
                                                             const std::vector<UUID>& uuids)
    : callback_(std::move(callback)), uuids_(uuids) {
  ZX_DEBUG_ASSERT(callback_);
}

void RemoteServiceManager::ServiceListRequest::Complete(att::Status status,
                                                        const ServiceMap& services) {
  TRACE_DURATION("bluetooth", "gatt::RemoteServiceManager::ServiceListRequest::Complete");

  ServiceList result;

  if (!status || services.empty()) {
    callback_(status, std::move(result));
    return;
  }

  for (const auto& iter : services) {
    auto& svc = iter.second;
    auto pred = [&svc](const UUID& uuid) { return svc->uuid() == uuid; };
    if (uuids_.empty() || std::find_if(uuids_.begin(), uuids_.end(), pred) != uuids_.end()) {
      result.push_back(iter.second);
    }
  }

  callback_(status, std::move(result));
}

RemoteServiceManager::RemoteServiceManager(std::unique_ptr<Client> client,
                                           async_dispatcher_t* gatt_dispatcher)
    : gatt_dispatcher_(gatt_dispatcher),
      client_(std::move(client)),
      initialized_(false),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(gatt_dispatcher_);
  ZX_DEBUG_ASSERT(client_);

  client_->SetNotificationHandler(fit::bind_member(this, &RemoteServiceManager::OnNotification));
}

RemoteServiceManager::~RemoteServiceManager() {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());

  client_->SetNotificationHandler({});
  ClearServices();

  // Resolve all pending requests with an error.
  att::Status status(HostError::kFailed);

  auto pending = std::move(pending_);
  while (!pending.empty()) {
    // This copies |services|.
    pending.front().Complete(status, services_);
    pending.pop();
  }
}

void RemoteServiceManager::Initialize(att::StatusCallback cb, std::vector<UUID> services) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());

  auto self = weak_ptr_factory_.GetWeakPtr();

  auto init_cb = [self, user_init_cb = std::move(cb)](att::Status status) {
    TRACE_DURATION("bluetooth", "gatt::RemoteServiceManager::Initialize::init_cb");
    if (!self)
      return;

    self->initialized_ = true;

    user_init_cb(status);

    // Notify pending ListService() requests.
    while (!self->pending_.empty()) {
      self->pending_.front().Complete(status, self->services_);
      self->pending_.pop();
    }
  };

  // Start out with the MTU exchange.
  client_->ExchangeMTU([self, init_cb = std::move(init_cb), services = std::move(services)](
                           att::Status status, uint16_t mtu) mutable {
    if (!self) {
      init_cb(att::Status(HostError::kFailed));
      return;
    }

    if (bt_is_error(status, TRACE, "gatt", "MTU exchange failed")) {
      init_cb(status);
      return;
    }

    Client::ServiceCallback svc_cb = [self](const ServiceData& service_data) {
      if (!self) {
        return;
      }

      att::Handle handle = service_data.range_start;
      auto iter = self->services_.find(handle);
      if (iter != self->services_.end()) {
        bt_log(ERROR, "gatt", "found duplicate service attribute handle! (%#.4x)", handle);
        return;
      }

      auto svc = fbl::AdoptRef(
          new RemoteService(service_data, self->client_->AsWeakPtr(), self->gatt_dispatcher_));
      if (!svc) {
        bt_log(DEBUG, "gatt", "failed to allocate RemoteService");
        return;
      }

      self->services_[handle] = svc;
    };

    auto status_cb = [self, init_cb = std::move(init_cb)](att::Status status) {
      TRACE_DURATION("bluetooth", "gatt::RemoteServiceManager::Initialize::MTUCallback::status_cb");
      if (!self) {
        init_cb(att::Status(HostError::kFailed));
        return;
      }

      // Service discovery support is mandatory for servers (v5.0, Vol 3,
      // Part G, 4.2).
      if (bt_is_error(status, TRACE, "gatt", "failed to discover services")) {
        // Clear services that were buffered so far.
        self->ClearServices();
      } else if (self->svc_watcher_) {
        // Notify all discovered services here.
        for (auto& iter : self->services_) {
          TRACE_DURATION("bluetooth", "gatt::RemoteServiceManager::svc_watcher_");
          self->svc_watcher_(iter.second);
        }
      }

      init_cb(status);
    };

    auto primary_discov_cb = [self, services, status_cb = std::move(status_cb),
                              svc_cb = svc_cb.share()](att::Status status) mutable {
      if (!self || !status) {
        status_cb(status);
        return;
      }

      auto secondary_discov_cb = [cb = std::move(status_cb)](att::Status status) mutable {
        // Not all GATT servers support the "secondary service" group type. We suppress the
        // "Unsupported Group Type" error code and simply report no services instead of treating it
        // as a fatal condition (errors propagated up the stack from here will cause the connection
        // to be terminated).
        if (status.is_protocol_error() &&
            status.protocol_error() == att::ErrorCode::kUnsupportedGroupType) {
          bt_log(DEBUG, "gatt", "peer does not support secondary services; ignoring ATT error");
          status = att::Status();
        }
        cb(status);
      };
      self->DiscoverServices(ServiceKind::SECONDARY, std::move(services), std::move(svc_cb),
                             std::move(secondary_discov_cb));
    };

    self->DiscoverServices(ServiceKind::PRIMARY, std::move(services), std::move(svc_cb),
                           std::move(primary_discov_cb));
  });
}

void RemoteServiceManager::DiscoverServices(ServiceKind kind, std::vector<UUID> services,
                                            Client::ServiceCallback svc_cb,
                                            att::StatusCallback status_cb) {
  if (!services.empty()) {
    client_->DiscoverServicesWithUuids(kind, std::move(svc_cb), std::move(status_cb),
                                       std::move(services));
  } else {
    client_->DiscoverServices(kind, std::move(svc_cb), std::move(status_cb));
  }
}

void RemoteServiceManager::ListServices(const std::vector<UUID>& uuids,
                                        ServiceListCallback callback) {
  ServiceListRequest request(std::move(callback), uuids);
  if (initialized_) {
    request.Complete(att::Status(), services_);
  } else {
    pending_.push(std::move(request));
  }
}

fbl::RefPtr<RemoteService> RemoteServiceManager::FindService(att::Handle handle) {
  auto iter = services_.find(handle);
  return iter == services_.end() ? nullptr : iter->second;
}

void RemoteServiceManager::ClearServices() {
  auto services = std::move(services_);
  for (auto& iter : services) {
    iter.second->ShutDown();
  }
}

void RemoteServiceManager::OnNotification(bool, att::Handle value_handle, const ByteBuffer& value) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());

  if (services_.empty()) {
    bt_log(DEBUG, "gatt", "ignoring notification from unknown service");
    return;
  }

  // Find the service that |value_handle| belongs to.
  auto iter = services_.upper_bound(value_handle);
  if (iter != services_.begin())
    --iter;

  // If |value_handle| is within the previous service then we found it.
  auto& svc = iter->second;
  ZX_DEBUG_ASSERT(value_handle >= svc->handle());

  if (svc->info().range_end >= value_handle) {
    svc->HandleNotification(value_handle, value);
  }
}

}  // namespace bt::gatt::internal
