/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "acl_connection_handler.h"

#include <hci/hci_packets.h>

#include "hci/address.h"
#include "os/log.h"

namespace test_vendor_lib {

using ::bluetooth::hci::Address;
using ::bluetooth::hci::AddressType;
using ::bluetooth::hci::AddressWithType;

bool AclConnectionHandler::HasHandle(uint16_t handle) const {
  return acl_connections_.count(handle) != 0;
}

uint16_t AclConnectionHandler::GetUnusedHandle() {
  while (HasHandle(last_handle_) ||
         isochronous_connection_handler_.HasHandle(last_handle_)) {
    last_handle_ = (last_handle_ + 1) % kReservedHandle;
  }
  uint16_t unused_handle = last_handle_;
  last_handle_ = (last_handle_ + 1) % kReservedHandle;
  return unused_handle;
}

bool AclConnectionHandler::CreatePendingConnection(
    Address addr, bool authenticate_on_connect) {
  if (classic_connection_pending_) {
    return false;
  }
  classic_connection_pending_ = true;
  pending_connection_address_ = addr;
  authenticate_pending_classic_connection_ = authenticate_on_connect;
  return true;
}

bool AclConnectionHandler::HasPendingConnection(Address addr) const {
  return classic_connection_pending_ && pending_connection_address_ == addr;
}

bool AclConnectionHandler::AuthenticatePendingConnection() const {
  return authenticate_pending_classic_connection_;
}

bool AclConnectionHandler::CancelPendingConnection(Address addr) {
  if (!classic_connection_pending_ || pending_connection_address_ != addr) {
    return false;
  }
  classic_connection_pending_ = false;
  pending_connection_address_ = Address::kEmpty;
  return true;
}

bool AclConnectionHandler::CreatePendingLeConnection(AddressWithType addr) {
  bool device_connected = false;
  for (auto pair : acl_connections_) {
    auto connection = std::get<AclConnection>(pair);
    if (connection.GetAddress() == addr) {
      device_connected = true;
    }
  }
  if (device_connected) {
    LOG_INFO("%s: %s is already connected", __func__, addr.ToString().c_str());
    return false;
  }
  if (le_connection_pending_) {
    LOG_INFO("%s: connection already pending", __func__);
    return false;
  }
  le_connection_pending_ = true;
  pending_le_connection_address_ = addr;
  return true;
}

bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
  return le_connection_pending_ && pending_le_connection_address_ == addr;
}

bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
  if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
    return false;
  }
  le_connection_pending_ = false;
  pending_le_connection_address_ =
      AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
  return true;
}

uint16_t AclConnectionHandler::CreateConnection(Address addr,
                                                Address own_addr) {
  if (CancelPendingConnection(addr)) {
    uint16_t handle = GetUnusedHandle();
    acl_connections_.emplace(
        handle,
        AclConnection{
            AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
            AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
            Phy::Type::BR_EDR});
    return handle;
  }
  return kReservedHandle;
}

uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
                                                  AddressWithType own_addr) {
  if (CancelPendingLeConnection(addr)) {
    uint16_t handle = GetUnusedHandle();
    acl_connections_.emplace(
        handle, AclConnection{addr, own_addr, Phy::Type::LOW_ENERGY});
    return handle;
  }
  return kReservedHandle;
}

bool AclConnectionHandler::Disconnect(uint16_t handle) {
  return acl_connections_.erase(handle) > 0;
}

uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
  for (auto pair : acl_connections_) {
    if (std::get<AclConnection>(pair).GetAddress() == addr) {
      return std::get<0>(pair);
    }
  }
  return kReservedHandle;
}

uint16_t AclConnectionHandler::GetHandleOnlyAddress(
    bluetooth::hci::Address addr) const {
  for (auto pair : acl_connections_) {
    if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
      return std::get<0>(pair);
    }
  }
  return kReservedHandle;
}

AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
  ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
  return acl_connections_.at(handle).GetAddress();
}

AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
  ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
  return acl_connections_.at(handle).GetOwnAddress();
}

void AclConnectionHandler::Encrypt(uint16_t handle) {
  if (!HasHandle(handle)) {
    return;
  }
  acl_connections_.at(handle).Encrypt();
}

bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
  if (!HasHandle(handle)) {
    return false;
  }
  return acl_connections_.at(handle).IsEncrypted();
}

void AclConnectionHandler::SetAddress(uint16_t handle,
                                      AddressWithType address) {
  if (!HasHandle(handle)) {
    return;
  }
  auto connection = acl_connections_.at(handle);
  connection.SetAddress(address);
}

Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
  if (!HasHandle(handle)) {
    return Phy::Type::BR_EDR;
  }
  return acl_connections_.at(handle).GetPhyType();
}

std::unique_ptr<bluetooth::hci::LeSetCigParametersCompleteBuilder>
AclConnectionHandler::SetCigParameters(
    uint8_t id, uint32_t sdu_interval_m_to_s, uint32_t sdu_interval_s_to_m,
    bluetooth::hci::ClockAccuracy /* accuracy */,
    bluetooth::hci::Packing packing, bluetooth::hci::Enable framed,
    uint16_t max_transport_latency_m_to_s_,
    uint16_t max_transport_latency_s_to_m_,
    std::vector<bluetooth::hci::CisParametersConfig>& streams) {
  std::vector<uint16_t> handles;
  GroupParameters group_parameters{
      .id = id,
      .sdu_interval_m_to_s = sdu_interval_m_to_s,
      .sdu_interval_s_to_m = sdu_interval_s_to_m,
      .interleaved = packing == bluetooth::hci::Packing::INTERLEAVED,
      .framed = framed == bluetooth::hci::Enable::ENABLED,
      .max_transport_latency_m_to_s = max_transport_latency_m_to_s_,
      .max_transport_latency_s_to_m = max_transport_latency_s_to_m_};
  std::vector<StreamParameters> stream_parameters;
  for (size_t i = 0; i < streams.size(); i++) {
    auto handle = GetUnusedHandle();
    StreamParameters a{.group_id = group_parameters.id,
                       .stream_id = streams[i].cis_id_,
                       .max_sdu_m_to_s = streams[i].max_sdu_m_to_s_,
                       .max_sdu_s_to_m = streams[i].max_sdu_s_to_m_,
                       .rtn_m_to_s = streams[i].rtn_m_to_s_,
                       .rtn_s_to_m = streams[i].rtn_s_to_m_,
                       .handle = handle};
    handles.push_back(handle);
    stream_parameters.push_back(std::move(a));
  }

  return isochronous_connection_handler_.SetCigParameters(
      group_parameters, stream_parameters, std::move(handles));
}

void AclConnectionHandler::CreatePendingCis(
    bluetooth::hci::CreateCisConfig config) {
  CisHandles handles;
  handles.cis_handle_ = config.cis_connection_handle_;
  handles.acl_handle_ = config.acl_connection_handle_;
  handles.remote_cis_handle_ = kReservedHandle;
  pending_streams_.emplace_back(std::move(handles));
}

bool AclConnectionHandler::ConnectCis(uint16_t handle) {
  size_t position;
  CisHandles connection;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_handle_) {
      LOG_INFO("Found handle 0x%04hx", handle);
      connection = pending_streams_[position];
      pending_streams_.erase(pending_streams_.begin() + position);
      connected_streams_.push_back(connection);
      ASSERT(connection.cis_handle_ != kReservedHandle);
      ASSERT(connection.acl_handle_ != kReservedHandle);
      ASSERT(connection.remote_cis_handle_ != kReservedHandle);
      return true;
    }
  }

  LOG_INFO("No pending CIS connection with handle 0x%04hx", handle);
  return false;
}

void AclConnectionHandler::SetRemoteCisHandle(uint16_t handle,
                                              uint16_t remote_handle) {
  for (size_t position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_handle_) {
      LOG_INFO("Added remote handle 0x%04hx to handle 0x%04hx", remote_handle,
               pending_streams_[position].cis_handle_);
      pending_streams_[position].remote_cis_handle_ = remote_handle;
      return;
    }
  }
  LOG_INFO("Couldn't find CIS connection with handle 0x%04hx", handle);
}

bool AclConnectionHandler::RejectCis(uint16_t handle) {
  size_t position;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (handle == pending_streams_[position].cis_handle_) {
      pending_streams_.erase(pending_streams_.begin() + position);
      break;
    }
  }
  if (position == pending_streams_.size()) {
    LOG_INFO("No pending connection with handle 0x%hx", handle);
    return false;
  }
  return true;
}

uint16_t AclConnectionHandler::GetPendingAclHandle(uint16_t cis_handle) const {
  size_t position;
  uint16_t handle = 0xffff;
  for (position = 0; position < pending_streams_.size(); position++) {
    if (cis_handle == pending_streams_[position].cis_handle_) {
      handle = pending_streams_[position].acl_handle_;
      break;
    }
  }
  if (position == pending_streams_.size()) {
    LOG_INFO("No pending connection with handle 0x%hx", cis_handle);
  }
  return handle;
}

bool AclConnectionHandler::DisconnectCis(uint16_t cis_handle) {
  size_t position;
  for (position = 0; position < connected_streams_.size(); position++) {
    if (cis_handle == connected_streams_[position].cis_handle_) {
      connected_streams_.erase(connected_streams_.begin() + position);
      break;
    }
  }
  if (position == connected_streams_.size()) {
    LOG_INFO("No connected stream 0x%hx", cis_handle);
    return false;
  }
  return true;
}

bluetooth::hci::ErrorCode AclConnectionHandler::RemoveCig(uint8_t cig_id) {
  for (const auto& stream : connected_streams_) {
    if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
        cig_id) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
  for (const auto& stream : pending_streams_) {
    if (isochronous_connection_handler_.GetGroupId(stream.cis_handle_) ==
        cig_id) {
      return bluetooth::hci::ErrorCode::COMMAND_DISALLOWED;
    }
  }
  auto status = isochronous_connection_handler_.RemoveCig(cig_id);
  if (status == bluetooth::hci::ErrorCode::SUCCESS) {
    // Clean up?
  }
  return status;
}

bool AclConnectionHandler::HasPendingCisConnection(uint16_t handle) const {
  for (const auto& config : pending_streams_) {
    if (config.cis_handle_ == handle) {
      return true;
    }
  }
  return false;
}

bool AclConnectionHandler::HasPendingCis() const {
  return !pending_streams_.empty();
}

bool AclConnectionHandler::HasConnectedCis(uint16_t handle) const {
  for (const auto& cs : connected_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  return false;
}

bool AclConnectionHandler::HasCisHandle(uint16_t handle) const {
  for (const auto& cs : pending_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  for (const auto& cs : connected_streams_) {
    if (handle == cs.cis_handle_) {
      return true;
    }
  }
  return isochronous_connection_handler_.HasHandle(handle);
}

uint16_t AclConnectionHandler::GetAclHandleForCisHandle(
    uint16_t cis_handle) const {
  for (const auto& cs : connected_streams_) {
    if (cis_handle == cs.cis_handle_) {
      return cs.acl_handle_;
    }
  }
  return kReservedHandle;
}

uint16_t AclConnectionHandler::GetRemoteCisHandleForCisHandle(
    uint16_t cis_handle) const {
  for (const auto& cs : connected_streams_) {
    if (cis_handle == cs.cis_handle_) {
      return cs.remote_cis_handle_;
    }
  }
  return kReservedHandle;
}

GroupParameters AclConnectionHandler::GetGroupParameters(uint8_t id) const {
  return isochronous_connection_handler_.GetGroupParameters(id);
}

StreamParameters AclConnectionHandler::GetStreamParameters(
    uint16_t handle) const {
  return isochronous_connection_handler_.GetStreamParameters(handle);
}

}  // namespace test_vendor_lib
