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

#include "helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sdp/status.h"

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

namespace fidlbredr = fuchsia::bluetooth::bredr;
using fidlbredr::DataElementType;
using fidlbredr::Profile;

namespace bthost {

namespace {

bt::l2cap::ChannelParameters FidlToChannelParameters(const fidlbredr::ChannelParameters& fidl) {
  bt::l2cap::ChannelParameters params;
  if (fidl.has_channel_mode()) {
    switch (fidl.channel_mode()) {
      case fidlbredr::ChannelMode::BASIC:
        params.mode = bt::l2cap::ChannelMode::kBasic;
        break;
      case fidlbredr::ChannelMode::ENHANCED_RETRANSMISSION:
        params.mode = bt::l2cap::ChannelMode::kEnhancedRetransmission;
        break;
      default:
        ZX_PANIC("FIDL channel parameter contains invalid mode");
    }
  }
  if (fidl.has_max_rx_sdu_size()) {
    params.max_rx_sdu_size = fidl.max_rx_sdu_size();
  }
  return params;
}

fidlbredr::ChannelMode ChannelModeToFidl(bt::l2cap::ChannelMode mode) {
  switch (mode) {
    case bt::l2cap::ChannelMode::kBasic:
      return fidlbredr::ChannelMode::BASIC;
      break;
    case bt::l2cap::ChannelMode::kEnhancedRetransmission:
      return fidlbredr::ChannelMode::ENHANCED_RETRANSMISSION;
      break;
    default:
      ZX_PANIC("Could not convert channel parameter mode to unsupported FIDL mode");
  }
}

fidlbredr::Channel ChannelSocketToFidlChannel(bt::l2cap::ChannelSocket chan_sock) {
  fidlbredr::Channel chan;
  if (!chan_sock) {
    return chan;
  }
  chan.set_socket(std::move(chan_sock.socket));
  chan.set_channel_mode(ChannelModeToFidl(chan_sock.params->mode));
  chan.set_max_tx_sdu_size(chan_sock.params->max_tx_sdu_size);
  return chan;
}

bool FidlToDataElement(const fidlbredr::DataElement& fidl, bt::sdp::DataElement* out) {
  ZX_DEBUG_ASSERT(out);
  switch (fidl.type) {
    case DataElementType::NOTHING:
      out->Set(nullptr);
      return true;
    case DataElementType::UNSIGNED_INTEGER: {
      if (!fidl.data.is_integer()) {
        return false;
      }
      if (fidl.size == 1) {
        out->Set(uint8_t(fidl.data.integer()));
      } else if (fidl.size == 2) {
        out->Set(uint16_t(fidl.data.integer()));
      } else if (fidl.size == 4) {
        out->Set(uint32_t(fidl.data.integer()));
      } else if (fidl.size == 8) {
        out->Set(uint64_t(fidl.data.integer()));
      } else {
        return false;
      }
      return true;
    }
    case DataElementType::SIGNED_INTEGER: {
      if (!fidl.data.is_integer()) {
        return false;
      }
      if (fidl.size == 1) {
        out->Set(int8_t(fidl.data.integer()));
      } else if (fidl.size == 2) {
        out->Set(int16_t(fidl.data.integer()));
      } else if (fidl.size == 4) {
        out->Set(int32_t(fidl.data.integer()));
      } else if (fidl.size == 8) {
        out->Set(int64_t(fidl.data.integer()));
      } else {
        return false;
      }
      return true;
    }
    case DataElementType::UUID: {
      if (!fidl.data.is_uuid()) {
        return false;
      }
      bt::UUID uuid;
      bool success = StringToUuid(fidl.data.uuid(), &uuid);
      if (!success) {
        return false;
      }
      out->Set(uuid);
      return true;
    }
    case DataElementType::STRING: {
      if (!fidl.data.is_str()) {
        return false;
      }
      out->Set(fidl.data.str());
      return true;
    }
    case DataElementType::BOOLEAN: {
      if (!fidl.data.is_b()) {
        return false;
      }
      out->Set(fidl.data.b());
      return true;
    }
    case DataElementType::SEQUENCE: {
      if (!fidl.data.is_sequence()) {
        return false;
      }
      bool success = true;
      std::vector<bt::sdp::DataElement> elems;
      for (const auto& fidl_elem : fidl.data.sequence()) {
        bt::sdp::DataElement it;
        success = FidlToDataElement(*fidl_elem, &it);
        if (!success) {
          return false;
        }
        elems.emplace_back(std::move(it));
      }
      out->Set(std::move(elems));
      return true;
    }
    default:
      return false;
  }
}

fidlbredr::DataElementPtr DataElementToFidl(const bt::sdp::DataElement* in) {
  auto elem = fidlbredr::DataElement::New();
  bt_log(SPEW, "sdp", "DataElementToFidl: %s", in->ToString().c_str());
  ZX_DEBUG_ASSERT(in);
  switch (in->type()) {
    case bt::sdp::DataElement::Type::kNull:
      elem->type = DataElementType::NOTHING;
      return elem;
    case bt::sdp::DataElement::Type::kUnsignedInt: {
      elem->type = DataElementType::UNSIGNED_INTEGER;
      auto size = in->size();
      if (size == bt::sdp::DataElement::Size::kOneByte) {
        elem->data.set_integer(*in->Get<uint8_t>());
      } else if (size == bt::sdp::DataElement::Size::kTwoBytes) {
        elem->data.set_integer(*in->Get<uint16_t>());
      } else if (size == bt::sdp::DataElement::Size::kFourBytes) {
        elem->data.set_integer(*in->Get<uint32_t>());
      } else if (size == bt::sdp::DataElement::Size::kEightBytes) {
        elem->data.set_integer(*in->Get<uint64_t>());
      } else {
        // TODO: handle 128-bit integers
        bt_log(DEBUG, "profile_server", "no 128-bit integer type yet");
        return nullptr;
      }
      return elem;
    }
    case bt::sdp::DataElement::Type::kSignedInt: {
      elem->type = DataElementType::SIGNED_INTEGER;
      auto size = in->size();
      if (size == bt::sdp::DataElement::Size::kOneByte) {
        elem->data.set_integer(*in->Get<int8_t>());
      } else if (size == bt::sdp::DataElement::Size::kTwoBytes) {
        elem->data.set_integer(*in->Get<int16_t>());
      } else if (size == bt::sdp::DataElement::Size::kFourBytes) {
        elem->data.set_integer(*in->Get<int32_t>());
      } else if (size == bt::sdp::DataElement::Size::kEightBytes) {
        elem->data.set_integer(*in->Get<int64_t>());
      } else {
        // TODO: handle 128-bit integers
        bt_log(DEBUG, "profile_server", "no 128-bit integer type yet");
        return nullptr;
      }
      return elem;
    }
    case bt::sdp::DataElement::Type::kUuid: {
      elem->type = DataElementType::UUID;
      auto uuid = in->Get<bt::UUID>();
      ZX_DEBUG_ASSERT(uuid);
      elem->data.uuid() = uuid->ToString();
      return elem;
    }
    case bt::sdp::DataElement::Type::kString: {
      elem->type = DataElementType::STRING;
      elem->data.str() = *in->Get<std::string>();
      return elem;
    }
    case bt::sdp::DataElement::Type::kBoolean: {
      elem->type = DataElementType::BOOLEAN;
      elem->data.set_b(*in->Get<bool>());
      return elem;
    }
    case bt::sdp::DataElement::Type::kSequence: {
      elem->type = DataElementType::SEQUENCE;
      std::vector<fidlbredr::DataElementPtr> elems;
      const bt::sdp::DataElement* it;
      for (size_t idx = 0; (it = in->At(idx)); ++idx) {
        elems.emplace_back(DataElementToFidl(it));
      }
      elem->data.set_sequence(std::move(elems));
      return elem;
    }
    case bt::sdp::DataElement::Type::kAlternative: {
      elem->type = DataElementType::ALTERNATIVE;
      std::vector<fidlbredr::DataElementPtr> elems;
      const bt::sdp::DataElement* it;
      for (size_t idx = 0; (it = in->At(idx)); ++idx) {
        elems.emplace_back(DataElementToFidl(it));
      }
      elem->data.set_sequence(std::move(elems));
      return elem;
    }
    case bt::sdp::DataElement::Type::kUrl: {
      ZX_PANIC("not implemented");
      break;
    }
  }
}

fidlbredr::ProtocolDescriptorPtr DataElementToProtocolDescriptor(const bt::sdp::DataElement* in) {
  auto desc = fidlbredr::ProtocolDescriptor::New();
  if (in->type() != bt::sdp::DataElement::Type::kSequence) {
    return nullptr;
  }
  const auto protocol_uuid = in->At(0)->Get<bt::UUID>();
  if (!protocol_uuid) {
    return nullptr;
  }
  desc->protocol = fidlbredr::ProtocolIdentifier(*protocol_uuid->As16Bit());
  const bt::sdp::DataElement* it;
  for (size_t idx = 1; (it = in->At(idx)); ++idx) {
    desc->params.push_back(std::move(*DataElementToFidl(it)));
  }

  return desc;
}

fidlbredr::ProfileDescriptorPtr DataElementToProfileDescriptor(const bt::sdp::DataElement* in) {
  auto desc = fidlbredr::ProfileDescriptor::New();
  if (in->type() != bt::sdp::DataElement::Type::kSequence) {
    return nullptr;
  }

  const bt::sdp::DataElement* profile_desc = in->At(0);
  const bt::sdp::DataElement* profile_elem = profile_desc->At(0);
  if (!profile_elem) {
    return nullptr;
  }
  const auto profile_uuid = profile_elem->Get<bt::UUID>();
  if (!profile_uuid) {
    return nullptr;
  }
  desc->profile_id = fidlbredr::ServiceClassProfileIdentifier(*profile_uuid->As16Bit());

  const bt::sdp::DataElement* version_elem = profile_desc->At(1);
  if (!version_elem) {
    return nullptr;
  }
  const auto version = version_elem->Get<uint16_t>();
  if (!version) {
    return nullptr;
  }

  desc->major_version = static_cast<uint8_t>(*version >> 8);
  desc->minor_version = static_cast<uint8_t>(*version & 0xFF);

  return desc;
}

void AddProtocolDescriptorList(
    bt::sdp::ServiceRecord* rec, bt::sdp::ServiceRecord::ProtocolListId id,
    const ::std::vector<fidlbredr::ProtocolDescriptor>& descriptor_list) {
  bt_log(SPEW, "profile_server", "ProtocolDescriptorList %d", id);
  for (auto& descriptor : descriptor_list) {
    bt::sdp::DataElement protocol_params;
    if (descriptor.params.size() > 1) {
      std::vector<bt::sdp::DataElement> params;
      for (auto& fidl_param : descriptor.params) {
        bt::sdp::DataElement bt_param;
        FidlToDataElement(fidl_param, &bt_param);
        params.emplace_back(std::move(bt_param));
      }
      protocol_params.Set(std::move(params));
    } else if (descriptor.params.size() == 1) {
      FidlToDataElement(descriptor.params.front(), &protocol_params);
    }

    bt_log(SPEW, "profile_server", "%d : %s", fidl::ToUnderlying(descriptor.protocol),
           protocol_params.ToString().c_str());
    rec->AddProtocolDescriptor(id, bt::UUID(static_cast<uint16_t>(descriptor.protocol)),
                               std::move(protocol_params));
  }
}

}  // namespace

ProfileServer::ProfileServer(fxl::WeakPtr<bt::gap::Adapter> adapter,
                             fidl::InterfaceRequest<Profile> request)
    : ServerBase(this, std::move(request)),
      last_service_id_(0),
      adapter_(adapter),
      weak_ptr_factory_(this) {}

ProfileServer::~ProfileServer() {
  if (adapter()) {
    // Unregister anything that we have registered.
    auto sdp = adapter()->sdp_server();
    for (const auto& it : registered_) {
      sdp->UnregisterService(it.second);
    }
    for (const auto& search_id : searches_) {
      adapter()->bredr_connection_manager()->RemoveServiceSearch(search_id);
    }
  }
}

void ProfileServer::AddService(fidlbredr::ServiceDefinition definition,
                               fidlbredr::SecurityLevel sec_level,
                               fidlbredr::ChannelParameters parameters,
                               AddServiceCallback callback) {
  // TODO: check that the service definition is valid for useful error messages

  bt::sdp::ServiceRecord rec;
  std::vector<bt::UUID> classes;
  for (auto& uuid_str : definition.service_class_uuids) {
    bt::UUID uuid;
    bt_log(SPEW, "profile_server", "Setting Service Class UUID %s", uuid_str.c_str());
    bool success = bt::StringToUuid(uuid_str, &uuid);
    if (!success) {
      callback(
          fidl_helpers::NewFidlError(ErrorCode::INVALID_ARGUMENTS, "Service class UUIDs not valid"),
          0);
      return;
    };
    classes.emplace_back(std::move(uuid));
  }

  rec.SetServiceClassUUIDs(classes);

  AddProtocolDescriptorList(&rec, bt::sdp::ServiceRecord::kPrimaryProtocolList,
                            definition.protocol_descriptors);

  size_t protocol_list_id = 1;
  if (definition.additional_protocol_descriptors.has_value()) {
    for (const auto& descriptor_list : *definition.additional_protocol_descriptors) {
      AddProtocolDescriptorList(&rec, protocol_list_id, descriptor_list);
      protocol_list_id++;
    }
  }

  for (const auto& profile : definition.profile_descriptors) {
    bt_log(SPEW, "profile_server", "Adding Profile %#x v%d.%d", profile.profile_id,
           profile.major_version, profile.minor_version);
    rec.AddProfile(bt::UUID(uint16_t(profile.profile_id)), profile.major_version,
                   profile.minor_version);
  }

  for (const auto& info : definition.information) {
    bt_log(SPEW, "profile_server", "Adding Info (%s): (%s, %s, %s)", info.language.c_str(),
           info.name.value_or("").c_str(), info.description.value_or("").c_str(),
           info.provider.value_or("").c_str());
    rec.AddInfo(info.language, info.name.value_or(""), info.description.value_or(""),
                info.provider.value_or(""));
  }

  if (definition.additional_attributes.has_value()) {
    for (const auto& attribute : *definition.additional_attributes) {
      bt::sdp::DataElement elem;
      FidlToDataElement(attribute.element, &elem);
      bt_log(SPEW, "profile_server", "Adding attribute %#x : %s", attribute.id,
             elem.ToString().c_str());
      rec.SetAttribute(attribute.id, std::move(elem));
    }
  }

  uint64_t next = last_service_id_ + 1;

  ZX_DEBUG_ASSERT(adapter());
  auto sdp = adapter()->sdp_server();
  ZX_DEBUG_ASSERT(sdp);

  auto handle = sdp->RegisterService(
      std::move(rec), FidlToChannelParameters(parameters),
      [this, next](auto chan_sock, auto handle, const auto& protocol_list) {
        OnChannelConnected(next, std::move(chan_sock), handle, std::move(protocol_list));
      });

  if (!handle) {
    callback(fidl_helpers::NewFidlError(ErrorCode::INVALID_ARGUMENTS,
                                        "Service definition was not valid"),
             0);
    return;
  };

  registered_.emplace(next, handle);
  last_service_id_ = next;
  callback(fidl_helpers::StatusToFidlDeprecated(bt::sdp::Status()), next);
}

void ProfileServer::RemoveService(uint64_t service_id) {
  auto it = registered_.find(service_id);
  if (it == registered_.end()) {
    bt_log(INFO, "profile_server", "RemoveService with unused id %lu", service_id);
    return;
  }

  ZX_DEBUG_ASSERT(adapter());
  auto server = adapter()->sdp_server();
  ZX_DEBUG_ASSERT(server);
  bool removed = server->UnregisterService(it->second);
  ZX_DEBUG_ASSERT(removed);
  registered_.erase(it);
}

void ProfileServer::AddSearch(fidlbredr::ServiceClassProfileIdentifier service_uuid,
                              std::vector<uint16_t> attr_ids) {
  bt::UUID search_uuid(static_cast<uint32_t>(service_uuid));
  std::unordered_set<bt::sdp::AttributeId> attributes(attr_ids.begin(), attr_ids.end());
  if (!attr_ids.empty()) {
    // Always request the ProfileDescriptor for the event
    attributes.insert(bt::sdp::kBluetoothProfileDescriptorList);
  }

  ZX_DEBUG_ASSERT(adapter());
  auto search_id = adapter()->bredr_connection_manager()->AddServiceSearch(
      search_uuid, std::move(attributes),
      [this](auto id, const auto& attrs) { OnServiceFound(id, attrs); });

  if (search_id) {
    searches_.emplace_back(search_id);
  }
}

void ProfileServer::ConnectL2cap(std::string peer_id, uint16_t channel,
                                 fidlbredr::ChannelParameters parameters,
                                 ConnectL2capCallback callback) {
  auto dev_id = fidl_helpers::PeerIdFromString(peer_id);
  if (!dev_id.has_value()) {
    callback(fidl_helpers::NewFidlError(ErrorCode::INVALID_ARGUMENTS, "invalid device ID"),
             fidlbredr::Channel());
    return;
  }

  auto connected_cb = [cb = callback.share()](auto chan_sock) {
    cb(fidl_helpers::StatusToFidlDeprecated(bt::sdp::Status()),
       ChannelSocketToFidlChannel(std::move(chan_sock)));
  };
  ZX_DEBUG_ASSERT(adapter());

  bool connecting = adapter()->bredr_connection_manager()->OpenL2capChannel(
      *dev_id, channel, FidlToChannelParameters(parameters), std::move(connected_cb),
      async_get_default_dispatcher());
  if (!connecting) {
    callback(fidl_helpers::NewFidlError(ErrorCode::NOT_FOUND,
                                        "Remote device not found - is it connected?"),
             fidlbredr::Channel());
  }
}

void ProfileServer::OnChannelConnected(uint64_t service_id, bt::l2cap::ChannelSocket chan_sock,
                                       bt::hci::ConnectionHandle handle,
                                       const bt::sdp::DataElement& protocol_list) {
  ZX_DEBUG_ASSERT(adapter());
  auto id = adapter()->bredr_connection_manager()->GetPeerId(handle);

  const auto* prot_seq = protocol_list.At(1);

  // If there isn't a second-level protocol, return the l2cap protocol
  if (!prot_seq) {
    prot_seq = protocol_list.At(0);
  }
  ZX_ASSERT(prot_seq);

  fidlbredr::ProtocolDescriptorPtr desc = DataElementToProtocolDescriptor(prot_seq);
  ZX_ASSERT(desc);

  binding()->events().OnConnected(id.ToString(), service_id,
                                  ChannelSocketToFidlChannel(std::move(chan_sock)),
                                  std::move(*desc));
}

void ProfileServer::OnServiceFound(
    bt::PeerId peer_id, const std::map<bt::sdp::AttributeId, bt::sdp::DataElement>& attributes) {
  // Convert ProfileDescriptor Attribute
  auto it = attributes.find(bt::sdp::kBluetoothProfileDescriptorList);
  if (it == attributes.end()) {
    bt_log(WARN, "profile_server",
           "Found service on %s didn't contain profile descriptor, dropping", bt_str(peer_id));
    return;
  }
  fidlbredr::ProfileDescriptorPtr desc = DataElementToProfileDescriptor(&it->second);

  // Add the rest of the attributes
  std::vector<fidlbredr::Attribute> fidl_attrs;

  for (const auto& it : attributes) {
    auto attr = fidlbredr::Attribute::New();
    attr->id = it.first;
    attr->element = std::move(*DataElementToFidl(&it.second));
    fidl_attrs.emplace_back(std::move(*attr));
  }

  binding()->events().OnServiceFound(peer_id.ToString(), std::move(*desc), std::move(fidl_attrs));
}

}  // namespace bthost
