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

#include <ddk/binding.h>
#include <zircon/status.h>

#include <memory>

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

using namespace bt;

namespace bthost {

namespace {

void CopyUUIDBytes(bt_gatt_uuid_t* dest, const UUID source) {
  memcpy(dest->bytes, source.value().data(), sizeof(dest->bytes));
}

bt_gatt_err_t AttErrorToDdkError(bt::att::ErrorCode error) {
  // Both of these enums *should* be identical and values.
  // Being explicit so we get compiler warnings if either changes.
  switch (error) {
    case bt::att::ErrorCode::kNoError:
      return BT_GATT_ERR_NO_ERROR;
    case bt::att::ErrorCode::kInvalidHandle:
      return BT_GATT_ERR_INVALID_HANDLE;
    case bt::att::ErrorCode::kReadNotPermitted:
      return BT_GATT_ERR_READ_NOT_PERMITTED;
    case bt::att::ErrorCode::kWriteNotPermitted:
      return BT_GATT_ERR_WRITE_NOT_PERMITTED;
    case bt::att::ErrorCode::kInvalidPDU:
      return BT_GATT_ERR_INVALID_PDU;
    case bt::att::ErrorCode::kInsufficientAuthentication:
      return BT_GATT_ERR_INSUFFICIENT_AUTHENTICATION;
    case bt::att::ErrorCode::kRequestNotSupported:
      return BT_GATT_ERR_REQUEST_NOT_SUPPORTED;
    case bt::att::ErrorCode::kInvalidOffset:
      return BT_GATT_ERR_INVALID_OFFSET;
    case bt::att::ErrorCode::kInsufficientAuthorization:
      return BT_GATT_ERR_INSUFFICIENT_AUTHORIZATION;
    case bt::att::ErrorCode::kPrepareQueueFull:
      return BT_GATT_ERR_PREPARE_QUEUE_FULL;
    case bt::att::ErrorCode::kAttributeNotFound:
      return BT_GATT_ERR_ATTRIBUTE_NOT_FOUND;
    case bt::att::ErrorCode::kAttributeNotLong:
      return BT_GATT_ERR_INVALID_ATTRIBUTE_VALUE_LENGTH;
    case bt::att::ErrorCode::kInsufficientEncryptionKeySize:
      return BT_GATT_ERR_INSUFFICIENT_ENCRYPTION_KEY_SIZE;
    case bt::att::ErrorCode::kInvalidAttributeValueLength:
      return BT_GATT_ERR_INVALID_ATTRIBUTE_VALUE_LENGTH;
    case bt::att::ErrorCode::kUnlikelyError:
      return BT_GATT_ERR_UNLIKELY_ERROR;
    case bt::att::ErrorCode::kInsufficientEncryption:
      return BT_GATT_ERR_INSUFFICIENT_ENCRYPTION;
    case bt::att::ErrorCode::kUnsupportedGroupType:
      return BT_GATT_ERR_UNSUPPORTED_GROUP_TYPE;
    case bt::att::ErrorCode::kInsufficientResources:
      return BT_GATT_ERR_INSUFFICIENT_RESOURCES;
  }
  return BT_GATT_ERR_NO_ERROR;
}

zx_status_t HostErrorToZxError(bt::HostError error) {
  switch (error) {
    case bt::HostError::kNoError:
      return ZX_OK;
    case bt::HostError::kNotFound:
      return ZX_ERR_NOT_FOUND;
    case bt::HostError::kNotReady:
      return ZX_ERR_SHOULD_WAIT;
    case bt::HostError::kTimedOut:
      return ZX_ERR_TIMED_OUT;
    case bt::HostError::kInvalidParameters:
      return ZX_ERR_INVALID_ARGS;
    case bt::HostError::kCanceled:
      return ZX_ERR_CANCELED;
    case bt::HostError::kNotSupported:
      return ZX_ERR_NOT_SUPPORTED;
    case bt::HostError::kLinkDisconnected:
      return ZX_ERR_CONNECTION_ABORTED;
    case bt::HostError::kOutOfMemory:
      return ZX_ERR_NO_MEMORY;
    default:
      return ZX_ERR_INTERNAL;
  }
}

bt_gatt_status_t AttStatusToDdkStatus(const bt::att::Status& status) {
  bt_gatt_status_t ddk_status = {
      .status = HostErrorToZxError(status.error()),
      .att_ecode = BT_GATT_ERR_NO_ERROR,
  };

  if (status.is_protocol_error()) {
    ddk_status.att_ecode = AttErrorToDdkError(status.protocol_error());
  }
  return ddk_status;
}

}  // namespace

GattRemoteServiceDevice::GattRemoteServiceDevice(
    zx_device_t* parent_device, bt::gatt::PeerId peer_id,
    fbl::RefPtr<bt::gatt::RemoteService> service)
    : loop_(&kAsyncLoopConfigNoAttachToThread),
      parent_device_(parent_device),
      dev_(nullptr),
      peer_id_(peer_id),
      service_(service) {
  dev_proto_.version = DEVICE_OPS_VERSION;
  dev_proto_.unbind = &GattRemoteServiceDevice::DdkUnbind;
  dev_proto_.release = &GattRemoteServiceDevice::DdkRelease;
}

GattRemoteServiceDevice::~GattRemoteServiceDevice() {
  if (dev_ != nullptr) {
    device_remove(dev_);
    dev_ = nullptr;
  }
}

bt_gatt_svc_protocol_ops_t GattRemoteServiceDevice::proto_ops_ = {
    .connect = &GattRemoteServiceDevice::OpConnect,
    .stop = &GattRemoteServiceDevice::OpStop,
    .read_characteristic = &GattRemoteServiceDevice::OpReadCharacteristic,
    .read_long_characteristic =
        &GattRemoteServiceDevice::OpReadLongCharacteristic,
    .write_characteristic = &GattRemoteServiceDevice::OpWriteCharacteristic,
    .enable_notifications = &GattRemoteServiceDevice::OpEnableNotifications,
};

zx_status_t GattRemoteServiceDevice::Bind() {
  // The bind program of an attaching device driver can either bind using to the
  // well known short 16 bit UUID of the service if available or the full 128
  // bit UUID (split across 4 32 bit values).
  const UUID& uuid = service_->uuid();
  uint32_t uuid16 = 0;

  if (uuid.CompactSize() == 2) {
    uuid16 =
        le16toh(*reinterpret_cast<const uint16_t*>(uuid.CompactView().data()));
  }

  uint32_t uuid01, uuid02, uuid03, uuid04 = 0;
  UInt128 uuid_bytes = uuid.value();

  uuid01 = le32toh(*reinterpret_cast<uint32_t*>(&uuid_bytes[0]));
  uuid02 = le32toh(*reinterpret_cast<uint32_t*>(&uuid_bytes[4]));
  uuid03 = le32toh(*reinterpret_cast<uint32_t*>(&uuid_bytes[8]));
  uuid04 = le32toh(*reinterpret_cast<uint32_t*>(&uuid_bytes[12]));

  zx_device_prop_t props[] = {
      {BIND_BT_GATT_SVC_UUID16, 0, uuid16},
      {BIND_BT_GATT_SVC_UUID128_1, 0, uuid01},
      {BIND_BT_GATT_SVC_UUID128_2, 0, uuid02},
      {BIND_BT_GATT_SVC_UUID128_3, 0, uuid03},
      {BIND_BT_GATT_SVC_UUID128_4, 0, uuid04},
  };

  bt_log(TRACE, "bt-host",
         "bt-gatt-svc binding to UUID16(%#04x), UUID128(1: %08x, 2: %08x,"
         " 3: %08x, 4: %08x), peer: %s",
         uuid16, uuid01, uuid02, uuid03, uuid04, bt_str(peer_id_));

  device_add_args_t args = {
      .version = DEVICE_ADD_ARGS_VERSION,
      .name = "bt-gatt-svc",
      .ctx = this,
      .ops = &dev_proto_,
      .proto_id = ZX_PROTOCOL_BT_GATT_SVC,
      .proto_ops = &proto_ops_,
      .props = props,
      .prop_count = 5,
      .flags = 0,
  };

  zx_status_t status = device_add(parent_device_, &args, &dev_);

  if (status != ZX_OK) {
    dev_ = nullptr;
    bt_log(ERROR, "bt-host",
           "bt-gatt-svc: failed to publish child gatt device: %s",
           zx_status_get_string(status));
    return status;
  }

  loop_.StartThread("bt-host bt-gatt-svc");

  return status;
}

void GattRemoteServiceDevice::Unbind() {
  bt_log(TRACE, "bt-host", "bt-gatt-svc: unbinding service");
  async::PostTask(loop_.dispatcher(), [this]() { loop_.Shutdown(); });
  loop_.JoinThreads();
}
void GattRemoteServiceDevice::Release() { dev_ = nullptr; }

void GattRemoteServiceDevice::Connect(bt_gatt_svc_connect_callback connect_cb,
                                      void* cookie) {
  async::PostTask(loop_.dispatcher(), [this, connect_cb, cookie]() {
    service_->DiscoverCharacteristics(
        [connect_cb, cookie](att::Status cb_status, const auto& chrcs) {
          auto ddk_chars = std::make_unique<bt_gatt_chr[]>(chrcs.size());
          size_t char_idx = 0;
          for (auto& chr : chrcs) {
            ddk_chars[char_idx].id = static_cast<bt_gatt_id_t>(chr.id());
            CopyUUIDBytes(&ddk_chars[char_idx].type, chr.info().type);
            ddk_chars[char_idx].properties = chr.info().properties;

            // TODO(zbowling): remote extended properties are not implemented.
            // ddk_chars[char_idx].extended_properties =
            // chr.info().extended_properties;

            auto& descriptors = chr.descriptors();
            if (descriptors.size() > 0) {
              ddk_chars[char_idx].descriptor_list =
                  new bt_gatt_descriptor_t[descriptors.size()];
              ddk_chars[char_idx].descriptor_count = descriptors.size();
              size_t desc_idx = 0;
              for (auto& descriptor : descriptors) {
                ddk_chars[char_idx].descriptor_list[desc_idx].id =
                    static_cast<bt_gatt_id_t>(descriptor.id());
                CopyUUIDBytes(
                    &ddk_chars[char_idx].descriptor_list[desc_idx].type,
                    descriptor.info().type);
                desc_idx++;
              }
            } else {
              ddk_chars[char_idx].descriptor_count = 0;
              ddk_chars[char_idx].descriptor_list = nullptr;
            }

            char_idx++;
          }

          bt_log(TRACE, "bt-host",
                 "bt-gatt-svc: connected; discovered %zu characteristics",
                 char_idx);
          bt_gatt_status_t status = {.status = ZX_OK};
          connect_cb(cookie, &status, ddk_chars.get(), char_idx);

          // Cleanup.
          for (char_idx = 0; char_idx < chrcs.size(); char_idx++) {
            if (ddk_chars[char_idx].descriptor_list != nullptr) {
              delete[] ddk_chars[char_idx].descriptor_list;
              ddk_chars[char_idx].descriptor_list = nullptr;
            }
          }
        },
        loop_.dispatcher());
  });

  return;
}

void GattRemoteServiceDevice::Stop() {
  // TODO(zbowling): Unregister notifications on the remote service.
  // We may replace this with an explicit unregister for notifications instead.
}

void GattRemoteServiceDevice::ReadCharacteristic(
    bt_gatt_id_t id, bt_gatt_svc_read_characteristic_callback read_cb,
    void* cookie) {
  auto read_callback = [id, cookie, read_cb](att::Status status,
                                             const ByteBuffer& buff) {
    bt_gatt_status_t ddk_status = AttStatusToDdkStatus(status);
    read_cb(cookie, &ddk_status, id, buff.data(), buff.size());
  };
  service_->ReadCharacteristic(static_cast<bt::gatt::IdType>(id),
                               std::move(read_callback), loop_.dispatcher());

  return;
}

void GattRemoteServiceDevice::ReadLongCharacteristic(
    bt_gatt_id_t id, uint16_t offset, size_t max_bytes,
    bt_gatt_svc_read_characteristic_callback read_cb, void* cookie) {
  auto read_callback = [id, cookie, read_cb](att::Status status,
                                             const ByteBuffer& buff) {
    bt_gatt_status_t ddk_status = AttStatusToDdkStatus(status);
    read_cb(cookie, &ddk_status, id, buff.data(), buff.size());
  };
  service_->ReadLongCharacteristic(static_cast<bt::gatt::IdType>(id), offset,
                                   max_bytes, std::move(read_callback),
                                   loop_.dispatcher());

  return;
}

void GattRemoteServiceDevice::WriteCharacteristic(
    bt_gatt_id_t id, const void* buff, size_t len,
    bt_gatt_svc_write_characteristic_callback write_cb, void* cookie) {
  auto* buf = static_cast<const uint8_t*>(buff);
  std::vector<uint8_t> data(buf, buf + len);
  if (write_cb == nullptr) {
    service_->WriteCharacteristicWithoutResponse(
        static_cast<bt::gatt::IdType>(id), std::move(data));
  } else {
    auto status_callback = [cookie, id, write_cb](bt::att::Status status) {
      bt_gatt_status_t ddk_status = AttStatusToDdkStatus(status);
      write_cb(cookie, &ddk_status, id);
    };

    service_->WriteCharacteristic(static_cast<bt::gatt::IdType>(id),
                                  std::move(data), std::move(status_callback),
                                  loop_.dispatcher());
  }
  return;
}

void GattRemoteServiceDevice::EnableNotifications(
    bt_gatt_id_t id, const bt_gatt_notification_value_t* value,
    bt_gatt_svc_enable_notifications_callback status_cb, void* cookie) {
  auto value_cb = *value;
  auto notif_callback = [id, value_cb](const ByteBuffer& buff) {
    value_cb.callback(value_cb.ctx, id, buff.data(), buff.size());
  };

  auto status_callback = [cookie, id, status_cb](bt::att::Status status,
                                                 bt::gatt::IdType handler_id) {
    bt_gatt_status_t ddk_status = AttStatusToDdkStatus(status);
    status_cb(cookie, &ddk_status, id);
  };

  service_->EnableNotifications(static_cast<bt::gatt::IdType>(id),
                                notif_callback, std::move(status_callback),
                                loop_.dispatcher());

  return;
}

}  // namespace bthost
