/*
 * Copyright 2020 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 <cstdint>

#include "osi/include/log.h"
#include "stack/btm/btm_ble_int.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_sec.h"
#include "stack/gatt/connection_manager.h"
#include "stack/include/acl_api.h"
#include "stack/include/bt_types.h"
#include "stack/include/l2cap_hci_link_interface.h"
#include "types/raw_address.h"

extern tBTM_CB btm_cb;

void btm_ble_advertiser_notify_terminated_legacy(uint8_t status,
                                                 uint16_t connection_handle);
void btm_ble_increment_link_topology_mask(uint8_t link_role);

bool maybe_resolve_address(RawAddress* bda, tBLE_ADDR_TYPE* bda_type);

static bool acl_ble_common_connection(const tBLE_BD_ADDR& address_with_type,
                                      uint16_t handle, tHCI_ROLE role,
                                      bool is_in_security_db,
                                      uint16_t conn_interval,
                                      uint16_t conn_latency,
                                      uint16_t conn_timeout) {
  if (role == HCI_ROLE_CENTRAL) {
    btm_cb.ble_ctr_cb.set_connection_state_idle();
    btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
  }

  // Inform any applications that a connection has completed.
  connection_manager::on_connection_complete(address_with_type.bda);

  // Allocate or update the security device record for this device
  btm_ble_connected(address_with_type.bda, handle, HCI_ENCRYPT_MODE_DISABLED,
                    role, address_with_type.type, is_in_security_db);

  // Update the link topology information for our device
  btm_ble_increment_link_topology_mask(role);

  // Inform l2cap of a potential connection.
  if (!l2cble_conn_comp(handle, role, address_with_type.bda,
                        address_with_type.type, conn_interval, conn_latency,
                        conn_timeout)) {
    btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
    LOG_WARN("Unable to complete l2cap connection");
    return false;
  }

  btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);

  /* Tell BTM Acl management about the link */
  btm_acl_created(address_with_type.bda, handle, role, BT_TRANSPORT_LE);

  return true;
}

void acl_ble_connection_complete(const tBLE_BD_ADDR& address_with_type,
                                 uint16_t handle, tHCI_ROLE role, bool match,
                                 uint16_t conn_interval, uint16_t conn_latency,
                                 uint16_t conn_timeout) {
  if (!acl_ble_common_connection(address_with_type, handle, role, match,
                                 conn_interval, conn_latency, conn_timeout)) {
    LOG_WARN("Unable to create non enhanced ble acl connection");
    return;
  }

  btm_ble_update_mode_operation(role, &address_with_type.bda, HCI_SUCCESS);

  if (role == HCI_ROLE_PERIPHERAL)
    btm_ble_advertiser_notify_terminated_legacy(HCI_SUCCESS, handle);
}

void acl_ble_enhanced_connection_complete(
    const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
    bool match, uint16_t conn_interval, uint16_t conn_latency,
    uint16_t conn_timeout, const RawAddress& local_rpa,
    const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type) {
  if (!acl_ble_common_connection(address_with_type, handle, role, match,
                                 conn_interval, conn_latency, conn_timeout)) {
    LOG_WARN("Unable to create enhanced ble acl connection");
    return;
  }

  btm_ble_refresh_local_resolvable_private_addr(address_with_type.bda,
                                                local_rpa);

  if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
    btm_ble_refresh_peer_resolvable_private_addr(
        address_with_type.bda, peer_rpa, tBTM_SEC_BLE::BTM_BLE_ADDR_RRA);
  btm_ble_update_mode_operation(role, &address_with_type.bda, HCI_SUCCESS);

  if (role == HCI_ROLE_PERIPHERAL)
    btm_ble_advertiser_notify_terminated_legacy(HCI_SUCCESS, handle);
}

static bool maybe_resolve_received_address(
    const tBLE_BD_ADDR& address_with_type,
    tBLE_BD_ADDR* resolved_address_with_type) {
  ASSERT(resolved_address_with_type != nullptr);

  *resolved_address_with_type = address_with_type;
  return maybe_resolve_address(&resolved_address_with_type->bda,
                               &resolved_address_with_type->type);
}

void acl_ble_enhanced_connection_complete_from_shim(
    const tBLE_BD_ADDR& address_with_type, uint16_t handle, tHCI_ROLE role,
    uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout,
    const RawAddress& local_rpa, const RawAddress& peer_rpa,
    tBLE_ADDR_TYPE peer_addr_type) {
  if (!connection_manager::remove_unconditional_from_shim(
          address_with_type.bda)) {
    LOG_WARN(
        "Unable to remove from legacy connection manager accept list addr:%s",
        PRIVATE_ADDRESS(address_with_type.bda));
  }

  tBLE_BD_ADDR resolved_address_with_type;
  const bool is_in_security_db = maybe_resolve_received_address(
      address_with_type, &resolved_address_with_type);

  acl_ble_enhanced_connection_complete(resolved_address_with_type, handle, role,
                                       is_in_security_db, conn_interval,
                                       conn_latency, conn_timeout, local_rpa,
                                       peer_rpa, peer_addr_type);

  // The legacy stack continues the LE connection after the read remote version
  // complete has been received.
  l2cble_notify_le_connection(address_with_type.bda);
  l2cble_use_preferred_conn_params(address_with_type.bda);
}

void acl_ble_connection_fail(const tBLE_BD_ADDR& address_with_type,
                             uint16_t handle, bool enhanced,
                             tHCI_STATUS status) {
  if (status != HCI_ERR_ADVERTISING_TIMEOUT) {
    btm_cb.ble_ctr_cb.set_connection_state_idle();
    btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
    btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
    connection_manager::on_connection_timed_out_from_shim(
        address_with_type.bda);
  } else {
    btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
    btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true);
  }
  btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, &address_with_type.bda,
                                status);
}

void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval,
                             uint16_t latency, uint16_t timeout,
                             tHCI_STATUS status);
void acl_ble_update_event_received(tHCI_STATUS status, uint16_t handle,
                                   uint16_t interval, uint16_t latency,
                                   uint16_t timeout) {
  l2cble_process_conn_update_evt(handle, status, interval, latency, timeout);

  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);

  if (!p_dev_rec) return;

  gatt_notify_conn_update(p_dev_rec->ble.pseudo_addr, interval, latency,
                          timeout, status);
}
