/*
    * Bluetooth.hpp
    * Top-level Bluetooth subsystem header
    * Copyright (c) 2026 Daniel Hammer
*/

#pragma once
#include <cstdint>
#include "Hci.hpp"

namespace Drivers::USB::Bluetooth {

    // Called by USB enumeration when a Bluetooth adapter is detected
    void RegisterAdapter(uint8_t slotId);

    // Complete any firmware-dependent bring-up that was deferred because the
    // adapter enumerated during the boot port scan, before the ramdisk (which
    // holds the firmware images) was mounted.  Safe to call unconditionally
    // once the boot filesystems are up; a no-op if nothing is pending.
    void ServiceDeferredInit();

    // Steady-state event service: drains the xHCI event ring + Bluetooth ACL
    // RX ring and flushes queued HCI replies.  Called from the idle loop so
    // inbound traffic (the headset's SDP/AVRCP queries, AVDTP commands, ACL
    // credits) is processed even when no syscall happens to be pumping a BT
    // wait loop.  Cheap no-op when the adapter is down; safe from any core
    // (PollEvents/DrainEvents/ProcessPendingCommands all self-serialize).
    void ServiceEvents();

    // Query adapter state
    bool IsInitialized();
    uint8_t GetSlotId();

    // Get Bluetooth device address (6 bytes)
    const uint8_t* GetBdAddr();

    // Change the adapter's BD_ADDR at runtime.  Drops any active links (their
    // pairing/crypto was bound to the old address), issues the Intel vendor
    // write (0xFC31), re-reads the controller's address into the cache and
    // re-asserts scan.  Returns true only if the controller reports the new
    // address.  Persisting the choice to 0:/config/bluetooth.toml is the
    // caller's job (userspace); the override is re-applied on boot by
    // ApplyConfiguredAddress() during init.  Bytes are in the same order as
    // GetBdAddr()/ReadBdAddr (addr[0] = least-significant octet).
    bool SetAddress(const uint8_t* addr);

    // Scan for nearby devices (blocking, up to timeoutMs)
    // Returns number of devices found; results written to buf
    int Scan(Hci::InquiryDevice* buf, int maxCount, uint32_t timeoutMs);

    // Initiate connection to a remote device by BD_ADDR
    // Returns 0 on success (connection established), -1 on failure
    int Connect(const uint8_t* bdAddr, uint32_t timeoutMs = 10000);

    // Disconnect a device by BD_ADDR
    // Returns 0 on success, -1 if not connected
    int Disconnect(const uint8_t* bdAddr);

    // List connected devices
    // Returns number of connected devices; info written to buf
    int ListConnected(Hci::ConnectionInfo* buf, int maxCount);

    // List bonded (paired) devices from the persisted link-key store.
    // Returns number written to buf (paired devices may be disconnected).
    int ListBonded(Hci::BondInfo* buf, int maxCount);

    // Forget a paired device: drop the link if connected and remove the bond
    // (so it must re-pair next time).  Returns 0 on success, -1 if not bonded.
    int ForgetDevice(const uint8_t* bdAddr);

}
