// Copyright 2023 The Pigweed Authors
//
// 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
//
//     https://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 "pw_bluetooth_sapphire/internal/host/hci/low_energy_connection.h"

#include "pw_bluetooth_sapphire/internal/host/transport/transport.h"

#pragma clang diagnostic ignored "-Wshadow"

namespace bt::hci {

LowEnergyConnection::LowEnergyConnection(
    hci_spec::ConnectionHandle handle,
    const DeviceAddress& local_address,
    const DeviceAddress& peer_address,
    const hci_spec::LEConnectionParameters& params,
    pw::bluetooth::emboss::ConnectionRole role,
    const Transport::WeakPtr& hci)
    : AclConnection(handle, local_address, peer_address, role, hci),
      WeakSelf(this),
      parameters_(params) {
  BT_ASSERT(local_address.type() != DeviceAddress::Type::kBREDR);
  BT_ASSERT(peer_address.type() != DeviceAddress::Type::kBREDR);
  BT_ASSERT(hci.is_alive());

  le_ltk_request_id_ = hci->command_channel()->AddLEMetaEventHandler(
      hci_spec::kLELongTermKeyRequestSubeventCode,
      fit::bind_member<&LowEnergyConnection::OnLELongTermKeyRequestEvent>(
          this));
}

LowEnergyConnection::~LowEnergyConnection() {
  // Unregister HCI event handlers.
  if (hci().is_alive()) {
    hci()->command_channel()->RemoveEventHandler(le_ltk_request_id_);
  }
}

bool LowEnergyConnection::StartEncryption() {
  if (state() != Connection::State::kConnected) {
    bt_log(DEBUG, "hci", "connection closed; cannot start encryption");
    return false;
  }
  if (role() != pw::bluetooth::emboss::ConnectionRole::CENTRAL) {
    bt_log(DEBUG, "hci", "only the central can start encryption");
    return false;
  }
  if (!ltk().has_value()) {
    bt_log(DEBUG, "hci", "connection has no LTK; cannot start encryption");
    return false;
  }

  auto cmd = EmbossCommandPacket::New<
      pw::bluetooth::emboss::LEEnableEncryptionCommandWriter>(
      hci_spec::kLEStartEncryption);
  auto params = cmd.view_t();
  params.connection_handle().Write(handle());
  params.random_number().Write(ltk()->rand());
  params.encrypted_diversifier().Write(ltk()->ediv());
  params.long_term_key().CopyFrom(
      pw::bluetooth::emboss::LinkKeyView(&ltk()->value()));

  auto event_cb = [self = GetWeakPtr(), handle = handle()](
                      auto id, const EventPacket& event) {
    if (!self.is_alive()) {
      return;
    }

    Result<> result = event.ToResult();
    if (bt_is_error(result,
                    ERROR,
                    "hci-le",
                    "could not set encryption on link %#.04x",
                    handle)) {
      if (self->encryption_change_callback()) {
        self->encryption_change_callback()(result.take_error());
      }
      return;
    }
    bt_log(DEBUG, "hci-le", "requested encryption start on %#.04x", handle);
  };
  if (!hci().is_alive()) {
    return false;
  }
  return hci()->command_channel()->SendCommand(
      std::move(cmd), std::move(event_cb), hci_spec::kCommandStatusEventCode);
}

void LowEnergyConnection::HandleEncryptionStatus(Result<bool> result,
                                                 bool /*key_refreshed*/) {
  // "On an authentication failure, the connection shall be automatically
  // disconnected by the Link Layer." (HCI_LE_Start_Encryption, Vol 2, Part E,
  // 7.8.24). We make sure of this by telling the controller to disconnect.
  if (result.is_error()) {
    Disconnect(pw::bluetooth::emboss::StatusCode::AUTHENTICATION_FAILURE);
  }

  if (!encryption_change_callback()) {
    bt_log(DEBUG,
           "hci",
           "%#.4x: no encryption status callback assigned",
           handle());
    return;
  }
  encryption_change_callback()(result);
}

CommandChannel::EventCallbackResult
LowEnergyConnection::OnLELongTermKeyRequestEvent(const EventPacket& event) {
  BT_ASSERT(event.event_code() == hci_spec::kLEMetaEventCode);
  BT_ASSERT(event.params<hci_spec::LEMetaEventParams>().subevent_code ==
            hci_spec::kLELongTermKeyRequestSubeventCode);

  auto* params =
      event.subevent_params<hci_spec::LELongTermKeyRequestSubeventParams>();
  if (!params) {
    bt_log(WARN, "hci", "malformed LE LTK request event");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  hci_spec::ConnectionHandle handle = le16toh(params->connection_handle);

  // Silently ignore the event as it isn't meant for this connection.
  if (handle != this->handle()) {
    return CommandChannel::EventCallbackResult::kContinue;
  }

  CommandChannel::CommandPacketVariant cmd;

  uint64_t rand = le64toh(params->random_number);
  uint16_t ediv = le16toh(params->encrypted_diversifier);

  bt_log(
      DEBUG, "hci", "LE LTK request - ediv: %#.4x, rand: %#.16lx", ediv, rand);
  if (ltk() && ltk()->rand() == rand && ltk()->ediv() == ediv) {
    cmd = CommandPacket::New(
        hci_spec::kLELongTermKeyRequestReply,
        sizeof(hci_spec::LELongTermKeyRequestReplyCommandParams));
    auto* params = std::get<std::unique_ptr<CommandPacket>>(cmd)
                       ->mutable_payload<
                           hci_spec::LELongTermKeyRequestReplyCommandParams>();

    params->connection_handle = htole16(handle);
    params->long_term_key = ltk()->value();
  } else {
    bt_log(DEBUG, "hci-le", "LTK request rejected");

    cmd = EmbossCommandPacket::New<
        pw::bluetooth::emboss::LELongTermKeyRequestNegativeReplyCommandWriter>(
        hci_spec::kLELongTermKeyRequestNegativeReply);
    auto view = std::get<EmbossCommandPacket>(cmd)
                    .view<pw::bluetooth::emboss::
                              LELongTermKeyRequestNegativeReplyCommandWriter>();
    view.connection_handle().Write(handle);
  }

  auto status_cb = [](auto id, const EventPacket& event) {
    hci_is_error(event, TRACE, "hci-le", "failed to reply to LTK request");
  };
  if (!hci().is_alive()) {
    return CommandChannel::EventCallbackResult::kRemove;
  }
  hci()->command_channel()->SendCommand(std::move(cmd), std::move(status_cb));
  return CommandChannel::EventCallbackResult::kContinue;
}

}  // namespace bt::hci
