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

#include <unordered_map>

#include "garnet/drivers/bluetooth/lib/att/bearer.h"
#include "garnet/drivers/bluetooth/lib/common/task_domain.h"
#include "garnet/drivers/bluetooth/lib/gatt/generic_attribute_service.h"
#include "garnet/drivers/bluetooth/lib/l2cap/channel.h"

#include "client.h"
#include "connection.h"
#include "remote_service.h"
#include "server.h"

namespace btlib {
namespace gatt {
namespace {

class Impl final : public GATT, common::TaskDomain<Impl, GATT> {
  using TaskDomainBase = common::TaskDomain<Impl, GATT>;

 public:
  explicit Impl(async_t* gatt_dispatcher)
      : TaskDomainBase(this, gatt_dispatcher), initialized_(false) {}

  ~Impl() override {
    FXL_DCHECK(!initialized_) << "gatt: ShutDown() must have been called!";
  }

  // GATT overrides:
  void Initialize() override {
    PostMessage([this] {
      FXL_DCHECK(!initialized_);

      local_services_ = std::make_unique<LocalServiceManager>();

      // Forwards Service Changed payloads to clients.
      auto send_indication_callback = [this](const std::string& peer_id,
                                             att::Handle handle,
                                             const common::ByteBuffer& value) {
        auto iter = connections_.find(peer_id);
        if (iter == connections_.end()) {
          FXL_LOG(WARNING) << "gatt: Peer not registered: " << peer_id;
          return;
        }
        iter->second.server()->SendNotification(handle, value.view(), true);
      };

      // Spin up Generic Attribute as the first service.
      gatt_service_ = std::make_unique<GenericAttributeService>(
          local_services_.get(), std::move(send_indication_callback));

      initialized_ = true;

      FXL_VLOG(1) << "gatt: initialized";
    });
  }

  void ShutDown() override { TaskDomainBase::ScheduleCleanUp(); }

  // Called on the GATT runner as a result of ScheduleCleanUp().
  void CleanUp() {
    FXL_VLOG(1) << "gatt: shutting down";

    initialized_ = false;
    connections_.clear();
    gatt_service_ = nullptr;
    local_services_ = nullptr;
    remote_service_callbacks_.clear();
  }

  void AddConnection(const std::string& peer_id,
                     fbl::RefPtr<l2cap::Channel> att_chan) override {
    FXL_VLOG(1) << "gatt: Add connection: " << peer_id;

    PostMessage([this, peer_id, att_chan] {
      FXL_DCHECK(local_services_);

      auto iter = connections_.find(peer_id);
      if (iter != connections_.end()) {
        FXL_LOG(WARNING) << "gatt: Peer is already registered: " << peer_id;
        return;
      }

      auto att_bearer = att::Bearer::Create(att_chan);
      if (!att_bearer) {
        // This can happen if the link closes before the Bearer activates the
        // channel.
        FXL_LOG(ERROR) << "gatt: Failed to initialize ATT bearer";
        att_chan->SignalLinkError();
        return;
      }

      connections_[peer_id] =
          internal::Connection(peer_id, att_bearer, local_services_->database(),
                               std::bind(&Impl::OnServiceAdded, this, peer_id,
                                         std::placeholders::_1),
                               dispatcher());
    });
  }

  void DiscoverServices(std::string peer_id) override {
    FXL_VLOG(1) << "gatt: Discover services: " << peer_id;

    PostMessage([this, peer_id = std::move(peer_id)] {
      auto iter = connections_.find(peer_id);
      if (iter == connections_.end()) {
        FXL_LOG(WARNING) << "gatt: Unknown peer: " << peer_id;
        return;
      }

      iter->second.Initialize();
    });
  }

  void RemoveConnection(std::string peer_id) override {
    FXL_VLOG(1) << "gatt: Remove connection: " << peer_id;
    PostMessage(
        [this, peer_id = std::move(peer_id)] {
            local_services_->DisconnectClient(peer_id);
            connections_.erase(peer_id);
        });
  }

  void RegisterService(ServicePtr service,
                       ServiceIdCallback callback,
                       ReadHandler read_handler,
                       WriteHandler write_handler,
                       ClientConfigCallback ccc_callback) override {
    PostMessage([this, svc = std::move(service), id_cb = std::move(callback),
                 rh = std::move(read_handler), wh = std::move(write_handler),
                 cccc = std::move(ccc_callback)]() mutable {
      IdType id;

      if (!initialized_) {
        FXL_VLOG(1) << "gatt: Cannot register service after shutdown";
        id = kInvalidId;
      } else {
        id = local_services_->RegisterService(std::move(svc), std::move(rh),
                                              std::move(wh), std::move(cccc));
      }

      id_cb(id);
    });
  }

  void UnregisterService(IdType service_id) override {
    PostMessage([this, service_id] {
      if (!initialized_)
        return;

      FXL_DCHECK(local_services_);
      local_services_->UnregisterService(service_id);
    });
  }

  void SendNotification(IdType service_id,
                        IdType chrc_id,
                        std::string peer_id,
                        ::fidl::VectorPtr<uint8_t> value,
                        bool indicate) override {
    PostMessage([this, svc_id = service_id, chrc_id, indicate,
                 peer_id = std::move(peer_id), value = value.take()] {
      if (!initialized_) {
        FXL_VLOG(3) << "gatt: Cannot notify after shutdown";
        return;
      }

      // There is nothing to do if the requested peer is not connected.
      auto iter = connections_.find(peer_id);
      if (iter == connections_.end()) {
        FXL_VLOG(2) << "gatt: Cannot notify disconnected peer: " << peer_id;
        return;
      }

      LocalServiceManager::ClientCharacteristicConfig config;
      if (!local_services_->GetCharacteristicConfig(svc_id, chrc_id, peer_id,
                                                    &config)) {
        FXL_VLOG(2) << "gatt: Peer has not configured characteristic: "
                    << peer_id;
        return;
      }

      // Make sure that the client has subscribed to the requested protocol
      // method.
      if ((indicate & !config.indicate) || (!indicate && !config.notify)) {
        FXL_VLOG(2) << "gatt: Peer has no configuration ("
                    << (indicate ? "ind" : "not") << "): " << peer_id;
        return;
      }

      iter->second.server()->SendNotification(
          config.handle, common::BufferView(value.data(), value.size()),
          indicate);
    });
  }

  void RegisterRemoteServiceWatcher(RemoteServiceWatcher callback,
                                    async_t* dispatcher) override {
    FXL_DCHECK(callback);
    PostMessage(
        [this, callback = std::move(callback), runner = dispatcher]() mutable {
          if (initialized_) {
            remote_service_callbacks_.emplace_back(std::move(callback),
                                                   std::move(runner));
          }
        });
  }

  void ListServices(std::string peer_id,
                    std::vector<common::UUID> uuids,
                    ServiceListCallback callback) override {
    FXL_DCHECK(callback);
    PostMessage([this, peer_id = std::move(peer_id),
                 callback = std::move(callback),
                 uuids = std::move(uuids)]() mutable {
      auto iter = connections_.find(peer_id);
      if (iter == connections_.end()) {
        // Connection not found.
        callback(att::Status(common::HostError::kNotFound), ServiceList());
        return;
      }
      iter->second.remote_service_manager()->ListServices(uuids,
                                                          std::move(callback));
    });
  }

  void FindService(std::string peer_id,
                   IdType service_id,
                   RemoteServiceCallback callback) override {
    PostMessage([this, service_id, peer_id = std::move(peer_id),
                 callback = std::move(callback)]() mutable {
      auto iter = connections_.find(peer_id);
      if (iter == connections_.end()) {
        // Connection not found.
        callback(nullptr);
        return;
      }
      callback(iter->second.remote_service_manager()->FindService(service_id));
    });
  }

 private:
  // Called when a new remote GATT service is discovered.
  void OnServiceAdded(const std::string& peer_id,
                      fbl::RefPtr<RemoteService> svc) {
    FXL_VLOG(1) << "gatt: Service added (peer_id: " << peer_id
                << ", handle: " << svc->handle()
                << ", uuid: " << svc->uuid().ToString();
    for (auto& handler : remote_service_callbacks_) {
      handler.Notify(peer_id, svc);
    }
  }

  // NOTE: The following objects MUST be initialized, accessed, and destroyed on
  // the GATT thread. They are not thread safe.
  bool initialized_;

  // The registry containing all local GATT services. This represents a single
  // ATT database.
  std::unique_ptr<LocalServiceManager> local_services_;

  // Local GATT service (first in database) for clients to subscribe to service
  // registration and removal.
  std::unique_ptr<GenericAttributeService> gatt_service_;

  // Contains the state of all GATT profile connections and their services.
  std::unordered_map<std::string, internal::Connection> connections_;

  // All registered remote service handlers.
  struct RemoteServiceHandler {
    RemoteServiceHandler(RemoteServiceWatcher watcher, async_t* dispatcher)
        : watcher_(std::move(watcher)), dispatcher_(dispatcher) {}

    RemoteServiceHandler() = default;
    RemoteServiceHandler(RemoteServiceHandler&&) = default;

    void Notify(const std::string& peer_id, fbl::RefPtr<RemoteService> svc) {
      if (!dispatcher_) {
        watcher_(peer_id, std::move(svc));
        return;
      }

      // NOTE: this makes a copy of |watcher_|.
      async::PostTask(dispatcher_, [peer_id, watcher = watcher_.share(),
                                    svc = std::move(svc)]() mutable {
        watcher(peer_id, std::move(svc));
      });
    }

   private:
    RemoteServiceWatcher watcher_;
    async_t* dispatcher_;

    FXL_DISALLOW_COPY_AND_ASSIGN(RemoteServiceHandler);
  };

  std::vector<RemoteServiceHandler> remote_service_callbacks_;

  FXL_DISALLOW_COPY_AND_ASSIGN(Impl);
};

}  // namespace

// static
fbl::RefPtr<GATT> GATT::Create(async_t* gatt_dispatcher) {
  return AdoptRef(new Impl(gatt_dispatcher));
}

}  // namespace gatt
}  // namespace btlib
