// Copyright 2023 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.

pub mod error;
pub mod event;

use std::collections::{HashMap, HashSet};
use std::sync::Arc;

use futures::stream::{BoxStream, FusedStream, SelectAll, Stream, StreamExt};
use futures::Future;
use parking_lot::Mutex;
use tracing::warn;

use bt_common::core::{AdvertisingSetId, PaInterval};
use bt_common::generic_audio::metadata_ltv::Metadata;
use bt_common::packet_encoding::Decodable;
use bt_gatt::client::{CharacteristicNotification, PeerService, ServiceCharacteristic};
use bt_gatt::types::{Handle, WriteMode};

use crate::client::error::{Error, ServiceError};
use crate::client::event::*;
use crate::types::*;

const READ_CHARACTERISTIC_BUFFER_SIZE: usize = 255;

/// Index into the vector of BIG subgroups. Valid value range is [0 to len of
/// BIG vector).
pub type SubgroupIndex = u8;

/// Synchronization information for BIG groups to tell which
/// BISes it should sync to.
pub type BigToBisSync = HashSet<(SubgroupIndex, BisIndex)>;

pub fn big_to_bis_sync_indices(info: &BigToBisSync) -> HashMap<SubgroupIndex, Vec<BisIndex>> {
    let mut sync_map = HashMap::new();
    for (ith_group, bis_index) in info.iter() {
        sync_map.entry(*ith_group).or_insert(Vec::new()).push(*bis_index);
    }
    sync_map
}

/// Keeps track of Source_ID and Broadcast_ID that are associated together.
/// Source_ID is assigned by the BASS server to a Broadcast Receive State
/// characteristic. If the remote peer with the BASS server autonomously
/// synchronized to a PA or accepted the Add Source operation, the server
/// selects an empty Broadcast Receive State characteristic to update or deletes
/// one of the existing one to update. However, because the concept of Source_ID
/// is unqiue to BASS, we track the Broadcast_ID that a Source_ID is associated
/// so that it can be used by upper layers.
#[derive(Default)]
pub(crate) struct KnownBroadcastSources(HashMap<Handle, BroadcastReceiveState>);

impl KnownBroadcastSources {
    fn new(receive_states: HashMap<Handle, BroadcastReceiveState>) -> Self {
        KnownBroadcastSources(receive_states)
    }

    /// Updates the value of the specified broadcast receive state
    /// characteristic. Returns the old value if it existed.
    fn update_state(
        &mut self,
        key: Handle,
        value: BroadcastReceiveState,
    ) -> Option<BroadcastReceiveState> {
        self.0.insert(key, value)
    }

    /// Given the broadcast ID, find the corresponding source ID.
    /// Returns none if the server doesn't know the specified broadcast source
    /// because a) the broadcast source was never added or discovered; or,
    /// b) the broadcast source was removed from remove operation; or,
    /// c) the broadcast source was removed by the server to add a different
    ///    broadcast source.
    fn source_id(&self, broadcast_id: &BroadcastId) -> Option<SourceId> {
        let Some(state) = self.state(broadcast_id) else {
            return None;
        };
        Some(state.source_id)
    }

    /// Gets the last updated broadcast receive state value.
    /// Returns none if the server doesn't know the specified broadcast source.
    fn state(&self, broadcast_id: &BroadcastId) -> Option<&ReceiveState> {
        self.0.iter().find_map(|(&_k, &ref v)| match v {
            BroadcastReceiveState::Empty => None,
            BroadcastReceiveState::NonEmpty(rs) => {
                if rs.broadcast_id() == *broadcast_id {
                    return Some(rs);
                }
                None
            }
        })
    }
}

/// Manages connection to the Broadcast Audio Scan Service at the
/// remote Scan Delegator and writes/reads characteristics to/from it.
pub struct BroadcastAudioScanServiceClient<T: bt_gatt::GattTypes> {
    gatt_client: T::PeerService,
    /// Broadcast Audio Scan Service only has one Broadcast Audio Scan Control
    /// Point characteristic according to BASS Section 3. There shall
    /// be one or more Broadcast Receive State characteristics.
    audio_scan_control_point: Handle,
    /// Broadcast Receive State characteristics can be used to determine the
    /// BASS status.
    broadcast_sources: Arc<Mutex<KnownBroadcastSources>>,
    /// Keeps track of the broadcast codes that were sent to the remote BASS
    /// server.
    broadcast_codes: HashMap<SourceId, [u8; 16]>,
    // GATT notification streams for BRS characteristic value changes.
    notification_streams: Option<
        SelectAll<BoxStream<'static, Result<CharacteristicNotification, bt_gatt::types::Error>>>,
    >,
}

impl<T: bt_gatt::GattTypes> BroadcastAudioScanServiceClient<T> {
    #[cfg(any(test, feature = "test-utils"))]
    pub fn create_for_test(gatt_client: T::PeerService, audio_scan_control_point: Handle) -> Self {
        Self {
            gatt_client,
            audio_scan_control_point,
            broadcast_sources: Default::default(),
            broadcast_codes: HashMap::new(),
            notification_streams: None,
        }
    }

    pub async fn create(gatt_client: T::PeerService) -> Result<Self, Error>
    where
        <T as bt_gatt::GattTypes>::NotificationStream: std::marker::Send,
    {
        // BASS server should have a single Broadcast Audio Scan Control Point
        // Characteristic.
        let bascp =
            ServiceCharacteristic::<T>::find(&gatt_client, BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID)
                .await
                .map_err(|e| Error::Gatt(e))?;
        if bascp.len() != 1 {
            let err = if bascp.len() == 0 {
                Error::Service(ServiceError::MissingCharacteristic)
            } else {
                Error::Service(ServiceError::ExtraScanControlPointCharacteristic)
            };
            return Err(err);
        }
        let bascp_handle = *bascp[0].handle();
        let brs_chars = Self::discover_brs_characteristics(&gatt_client).await?;
        let mut c = Self {
            gatt_client,
            audio_scan_control_point: bascp_handle,
            broadcast_sources: Arc::new(Mutex::new(KnownBroadcastSources::new(brs_chars))),
            broadcast_codes: HashMap::new(),
            notification_streams: None,
        };
        c.register_notifications();
        Ok(c)
    }

    // Discover all the Broadcast Receive State characteristics.
    // On success, returns the HashMap of all Broadcast Received State
    // Characteristics.
    async fn discover_brs_characteristics(
        gatt_client: &T::PeerService,
    ) -> Result<HashMap<Handle, BroadcastReceiveState>, Error> {
        let brs = ServiceCharacteristic::<T>::find(gatt_client, BROADCAST_RECEIVE_STATE_UUID)
            .await
            .map_err(|e| Error::Gatt(e))?;
        if brs.len() == 0 {
            return Err(Error::Service(ServiceError::MissingCharacteristic));
        }
        let mut brs_map = HashMap::new();
        for c in brs {
            // Read the value of the Broadcast Recieve State at the time of discovery for
            // record.
            let mut buf = vec![0; READ_CHARACTERISTIC_BUFFER_SIZE];
            match c.read(&mut buf[..]).await {
                Ok(read_bytes) => match BroadcastReceiveState::decode(&buf[0..read_bytes]) {
                    Ok((decoded, _decoded_bytes)) => {
                        brs_map.insert(*c.handle(), decoded);
                        continue;
                    }
                    Err(e) => warn!(
                        "Failed to decode characteristic ({:?}) to Broadcast Receive State value: {:?}",
                        *c.handle(),
                        e
                    ),
                },
                Err(e) => warn!("Failed to read characteristic ({:?}) value: {:?}", *c.handle(), e),
            }
            brs_map.insert(*c.handle(), BroadcastReceiveState::Empty);
        }
        Ok(brs_map)
    }

    fn register_notifications(&mut self)
    where
        <T as bt_gatt::GattTypes>::NotificationStream: std::marker::Send,
    {
        let mut notification_streams = SelectAll::new();
        {
            let lock = self.broadcast_sources.lock();
            for handle in lock.0.keys() {
                let stream = self.gatt_client.subscribe(&handle);
                notification_streams.push(stream.boxed());
            }
        }
        self.notification_streams = Some(notification_streams);
    }

    /// Returns a stream that can be used by the upper layer to poll for
    /// BroadcastAudioScanServiceEvent. BroadcastAudioScanServiceEvents are
    /// generated based on BRS characteristic change received from GATT
    /// notification that are processed by BroadcastAudioScanServiceClient.
    /// This method should only be called once.
    /// Returns an error if the method is called for a second time.
    pub fn take_event_stream(
        &mut self,
    ) -> Option<impl Stream<Item = Result<Event, Error>> + FusedStream> {
        let notification_streams = self.notification_streams.take();
        let Some(streams) = notification_streams else {
            return None;
        };
        let event_stream = EventStream::new(streams, self.broadcast_sources.clone());
        Some(event_stream)
    }

    /// Write to the Broadcast Audio Scan Control Point characteristic in
    /// without response mode.
    fn write_to_bascp(
        &self,
        op: impl ControlPointOperation,
    ) -> impl Future<Output = Result<(), Error>> + '_ {
        let handle = self.audio_scan_control_point;
        let mut buf = vec![0; op.encoded_len()];
        let encode_res = op.encode(&mut buf[..]);
        async move {
            match encode_res {
                Err(e) => Err(Error::Packet(e)),
                Ok(_) => self
                    .gatt_client
                    .write_characteristic(&handle, WriteMode::WithoutResponse, 0, buf.as_slice())
                    .await
                    .map_err(|e| Error::Gatt(e)),
            }
        }
    }

    fn get_source_id(&self, broadcast_id: &BroadcastId) -> Result<SourceId, Error> {
        self.broadcast_sources
            .lock()
            .source_id(broadcast_id)
            .ok_or(Error::UnknownBroadcastSource(*broadcast_id))
    }

    /// Returns a clone of the latest known broadcast audio receive state of the
    /// specified broadcast source given its broadcast id.
    fn get_broadcast_source_state(&self, broadcast_id: &BroadcastId) -> Option<ReceiveState> {
        let lock = self.broadcast_sources.lock();
        lock.state(broadcast_id).clone().map(|rs| rs.clone())
    }

    /// Indicates to the remote BASS server that we have started scanning for
    /// broadcast sources on behalf of it. If the scan delegator that serves
    /// the BASS server is collocated with a broadcast sink, this may or may
    /// not change the scanning behaviour of the the broadcast sink.
    pub async fn remote_scan_started(&mut self) -> Result<(), Error> {
        let op = RemoteScanStartedOperation;
        self.write_to_bascp(op).await
    }

    /// Indicates to the remote BASS server that we have stopped scanning for
    /// broadcast sources on behalf of it.
    pub async fn remote_scan_stopped(&mut self) -> Result<(), Error> {
        let op = RemoteScanStoppedOperation;
        self.write_to_bascp(op).await
    }

    /// Provides the BASS server with information regarding a Broadcast Source.
    pub async fn add_broadcast_source(
        &mut self,
        broadcast_id: BroadcastId,
        address_type: AddressType,
        advertiser_address: [u8; ADDRESS_BYTE_SIZE],
        sid: AdvertisingSetId,
        pa_sync: PaSync,
        pa_interval: PaInterval,
        subgroups: Vec<BigSubgroup>,
    ) -> Result<(), Error> {
        let op = AddSourceOperation::new(
            address_type,
            advertiser_address,
            sid,
            broadcast_id,
            pa_sync,
            pa_interval,
            subgroups,
        );
        self.write_to_bascp(op).await
    }

    /// Requests the BASS server to add or update Metadata for the Broadcast
    /// Source, and/or to request the server to synchronize to, or to stop
    /// synchronization to, a PA and/or a BIS.
    ///
    /// # Arguments
    ///
    /// * `broadcast_id` - id of the broadcast source to modify
    /// * `pa_sync` - pa sync mode the scan delegator peer should attempt to be
    ///   in
    /// * `pa_interval` - updated PA interval value. If none, unknown value is
    ///   used
    /// * `bis_sync` - desired BIG to BIS synchronization information. If empty,
    ///   it's not updated
    /// * `metadata_map` - map of updated metadata for BIGs. If a mapping does
    ///   not exist for a BIG, that BIG's metadata is not updated
    pub async fn modify_broadcast_source(
        &mut self,
        broadcast_id: BroadcastId,
        pa_sync: PaSync,
        pa_interval: Option<PaInterval>,
        bis_sync: Option<BigToBisSync>,
        metadata_map: Option<HashMap<SubgroupIndex, Vec<Metadata>>>,
    ) -> Result<(), Error> {
        let op = {
            let mut state = self
                .get_broadcast_source_state(&broadcast_id)
                .ok_or(Error::UnknownBroadcastSource(broadcast_id))?;

            // Update BIS_Sync param for BIGs if applicable.
            if let Some(m) = bis_sync {
                let sync_map = big_to_bis_sync_indices(&m);

                for (big_index, group) in state.subgroups.iter_mut().enumerate() {
                    if let Some(bis_indices) = sync_map.get(&(big_index as u8)) {
                        group.bis_sync.set_sync(bis_indices).map_err(|e| Error::Packet(e))?;
                    }
                }
            }
            // Update metadata for BIGs if applicable.
            if let Some(mut m) = metadata_map {
                for (big_index, group) in state.subgroups.iter_mut().enumerate() {
                    if let Some(metadata) = m.remove(&(big_index as u8)) {
                        group.metadata = metadata;
                    }
                }

                // Left over metadata values are new subgroups that are to be added. New
                // subgroups can only be added if the subgroup index is
                // contiguous to existing subgroups.
                let mut new_big_indices: Vec<&u8> = m.keys().collect();
                new_big_indices.sort();
                for big_index in new_big_indices {
                    if (*big_index as usize) != state.subgroups.len() {
                        warn!("cannot add new [{big_index}th] subgroup");
                        break;
                    }
                    let new_subgroup = BigSubgroup::new(None).with_metadata(m[big_index].clone());
                    state.subgroups.push(new_subgroup);
                }
            }

            ModifySourceOperation::new(
                state.source_id,
                pa_sync,
                pa_interval.unwrap_or(PaInterval::unknown()),
                state.subgroups,
            )
        };
        self.write_to_bascp(op).await
    }

    pub async fn remove_broadcast_source(
        &mut self,
        broadcast_id: BroadcastId,
    ) -> Result<(), Error> {
        let source_id = self.get_source_id(&broadcast_id)?;

        let op = RemoveSourceOperation::new(source_id);
        self.write_to_bascp(op).await
    }

    /// Sets the broadcast code for a particular broadcast stream.
    pub async fn set_broadcast_code(
        &mut self,
        broadcast_id: BroadcastId,
        broadcast_code: [u8; 16],
    ) -> Result<(), Error> {
        let source_id = self.get_source_id(&broadcast_id)?;

        let op = SetBroadcastCodeOperation::new(source_id, broadcast_code.clone());
        self.write_to_bascp(op).await?;

        // Save the broadcast code we sent.
        self.broadcast_codes.insert(source_id, broadcast_code);
        Ok(())
    }

    /// Returns a list of currently known broadcast sources at the time
    /// this method was called.
    pub fn known_broadcast_sources(&self) -> Vec<(Handle, BroadcastReceiveState)> {
        let lock = self.broadcast_sources.lock();
        let mut brs = Vec::new();
        for (k, v) in lock.0.iter() {
            brs.push((*k, v.clone()));
        }
        brs
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::task::Poll;

    use assert_matches::assert_matches;
    use futures::executor::block_on;
    use futures::{pin_mut, FutureExt};

    use bt_common::core::AdvertisingSetId;
    use bt_common::Uuid;
    use bt_gatt::test_utils::*;
    use bt_gatt::types::{
        AttributePermissions, CharacteristicProperties, CharacteristicProperty, Handle,
    };
    use bt_gatt::Characteristic;

    const RECEIVE_STATE_1_HANDLE: Handle = Handle(1);
    const RECEIVE_STATE_2_HANDLE: Handle = Handle(2);
    const RECEIVE_STATE_3_HANDLE: Handle = Handle(3);
    const RANDOME_CHAR_HANDLE: Handle = Handle(4);
    const AUDIO_SCAN_CONTROL_POINT_HANDLE: Handle = Handle(5);

    fn setup_client() -> (BroadcastAudioScanServiceClient<FakeTypes>, FakePeerService) {
        let mut fake_peer_service = FakePeerService::new();
        // Add 3 Broadcast Receive State Characteristics, 1 Broadcast Audio Scan Control
        // Point Characteristic, and 1 random one.
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RECEIVE_STATE_1_HANDLE,
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RECEIVE_STATE_2_HANDLE,
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RECEIVE_STATE_3_HANDLE,
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RANDOME_CHAR_HANDLE,
                uuid: Uuid::from_u16(0x1234),
                properties: CharacteristicProperties(vec![CharacteristicProperty::Notify]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: AUDIO_SCAN_CONTROL_POINT_HANDLE,
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let create_result =
            BroadcastAudioScanServiceClient::<FakeTypes>::create(fake_peer_service.clone());
        pin_mut!(create_result);
        let polled = create_result.poll_unpin(&mut noop_cx);
        let Poll::Ready(Ok(client)) = polled else {
            panic!("Expected BroadcastAudioScanServiceClient to be succesfully created");
        };

        (client, fake_peer_service)
    }

    #[test]
    fn create_client() {
        let (client, _) = setup_client();

        // Check that all the characteristics have been discovered.
        assert_eq!(client.audio_scan_control_point, AUDIO_SCAN_CONTROL_POINT_HANDLE);
        let broadcast_sources = client.known_broadcast_sources();
        assert_eq!(broadcast_sources.len(), 3);
        assert!(broadcast_sources.iter().find(|v| v.0 == RECEIVE_STATE_1_HANDLE).is_some());
        assert!(broadcast_sources.iter().find(|v| v.0 == RECEIVE_STATE_2_HANDLE).is_some());
        assert!(broadcast_sources.iter().find(|v| v.0 == RECEIVE_STATE_3_HANDLE).is_some());
    }

    #[test]
    fn create_client_fails_missing_characteristics() {
        // Missing scan control point characteristic.
        let mut fake_peer_service = FakePeerService::new();
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(1),
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let create_result =
            BroadcastAudioScanServiceClient::<FakeTypes>::create(fake_peer_service.clone());

        pin_mut!(create_result);
        let polled = create_result.poll_unpin(&mut noop_cx);
        let Poll::Ready(Err(_)) = polled else {
            panic!("Expected BroadcastAudioScanServiceClient to have failed");
        };

        // Missing receive state characteristic.
        let mut fake_peer_service: FakePeerService = FakePeerService::new();
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(1),
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let create_result =
            BroadcastAudioScanServiceClient::<FakeTypes>::create(fake_peer_service.clone());
        pin_mut!(create_result);
        let polled = create_result.poll_unpin(&mut noop_cx);
        let Poll::Ready(Err(_)) = polled else {
            panic!("Expected BroadcastAudioScanServiceClient to have failed");
        };
    }

    #[test]
    fn create_client_fails_duplicate_characteristics() {
        // More than one scan control point characteristics.
        let mut fake_peer_service = FakePeerService::new();
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(1),
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(2),
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(3),
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperties(vec![CharacteristicProperty::Broadcast]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let create_result =
            BroadcastAudioScanServiceClient::<FakeTypes>::create(fake_peer_service.clone());
        pin_mut!(create_result);
        let polled = create_result.poll_unpin(&mut noop_cx);
        let Poll::Ready(Err(_)) = polled else {
            panic!("Expected BroadcastAudioScanServiceClient to have failed");
        };
    }

    #[test]
    fn start_event_stream() {
        let (mut client, mut fake_peer_service) = setup_client();
        let mut event_stream = client.take_event_stream().expect("stream was created");

        // Send notification for updating BRS characteristic to indicate it's synced and
        // requires broadcast code.
        #[rustfmt::skip]
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RECEIVE_STATE_2_HANDLE,
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![
                0x02, AddressType::Public as u8,                      // source id and address type
                0x02, 0x03, 0x04, 0x05, 0x06, 0x07,                   // address
                0x01, 0x02, 0x03, 0x04,                               // ad set id and broadcast id
                PaSyncState::Synced as u8,
                EncryptionStatus::BroadcastCodeRequired.raw_value(),
                0x00,                                                 // no subgroups
            ],
        );

        // Check that synced and broadcast code required events were sent out.
        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());

        let recv_fut = event_stream.select_next_some();
        let event = block_on(recv_fut).expect("should receive event");
        assert_eq!(
            event,
            Event::AddedBroadcastSource(
                BroadcastId(0x040302),
                PaSyncState::Synced,
                EncryptionStatus::BroadcastCodeRequired
            )
        );

        // Stream should be pending since no more notifications.
        assert!(event_stream.poll_next_unpin(&mut noop_cx).is_pending());

        // Send notification for updating BRS characteristic to indicate it requires
        // sync info. Notification for updating the BRS characteristic value for
        // characteristic with handle 3.
        #[rustfmt::skip]
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RECEIVE_STATE_3_HANDLE,
                uuid: BROADCAST_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![
                0x03, AddressType::Public as u8,             // source id and address type
                0x03, 0x04, 0x05, 0x06, 0x07, 0x08,          // address
                0x01, 0x03, 0x04, 0x05,                      // ad set id and broadcast id
                PaSyncState::SyncInfoRequest as u8,
                EncryptionStatus::NotEncrypted.raw_value(),
                0x00,                                        // no subgroups
            ],
        );

        let recv_fut = event_stream.select_next_some();
        let event = block_on(recv_fut).expect("should receive event");
        assert_eq!(
            event,
            Event::AddedBroadcastSource(
                BroadcastId(0x050403),
                PaSyncState::SyncInfoRequest,
                EncryptionStatus::NotEncrypted
            )
        );

        // Stream should be pending since no more notifications.
        assert!(event_stream.poll_next_unpin(&mut noop_cx).is_pending());
    }

    #[test]
    fn remote_scan_started() {
        let (mut client, mut fake_peer_service) = setup_client();

        fake_peer_service.expect_characteristic_value(&AUDIO_SCAN_CONTROL_POINT_HANDLE, vec![0x01]);

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let op_fut = client.remote_scan_started();
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn remote_scan_stopped() {
        let (mut client, mut fake_peer_service) = setup_client();

        fake_peer_service.expect_characteristic_value(&AUDIO_SCAN_CONTROL_POINT_HANDLE, vec![0x00]);

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let op_fut = client.remote_scan_stopped();
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn add_broadcast_source() {
        let (mut client, mut fake_peer_service) = setup_client();

        fake_peer_service.expect_characteristic_value(
            &AUDIO_SCAN_CONTROL_POINT_HANDLE,
            vec![
                0x02, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0xFF,
                0xFF, 0x00,
            ],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let op_fut = client.add_broadcast_source(
            BroadcastId(0x11),
            AddressType::Public,
            [0x04, 0x10, 0x00, 0x00, 0x00, 0x00],
            AdvertisingSetId(1),
            PaSync::DoNotSync,
            PaInterval::unknown(),
            vec![],
        );
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn modify_broadcast_source() {
        let (mut client, mut fake_peer_service) = setup_client();

        // Manually update the broadcast source tracker for testing purposes.
        // In practice, this would have been updated from BRS value change notification.
        client.broadcast_sources.lock().update_state(
            RECEIVE_STATE_1_HANDLE,
            BroadcastReceiveState::NonEmpty(ReceiveState {
                source_id: 0x11,
                source_address_type: AddressType::Public,
                source_address: [1, 2, 3, 4, 5, 6],
                source_adv_sid: AdvertisingSetId(1),
                broadcast_id: BroadcastId(0x11),
                pa_sync_state: PaSyncState::Synced,
                big_encryption: EncryptionStatus::BroadcastCodeRequired,
                subgroups: vec![],
            }),
        );

        #[rustfmt::skip]
        fake_peer_service.expect_characteristic_value(
            &AUDIO_SCAN_CONTROL_POINT_HANDLE,
            vec![
                0x03, 0x11, 0x00,  // opcode, source id, pa sync
                0xAA, 0xAA, 0x00,  // pa sync, pa interval, num of subgroups
            ],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let op_fut = client.modify_broadcast_source(
            BroadcastId(0x11),
            PaSync::DoNotSync,
            Some(PaInterval(0xAAAA)),
            None,
            None,
        );
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn modify_broadcast_source_updates_groups() {
        let (mut client, mut fake_peer_service) = setup_client();

        // Manually update the broadcast source tracker for testing purposes.
        // In practice, this would have been updated from BRS value change notification.
        client.broadcast_sources.lock().update_state(
            RECEIVE_STATE_1_HANDLE,
            BroadcastReceiveState::NonEmpty(ReceiveState {
                source_id: 0x11,
                source_address_type: AddressType::Public,
                source_address: [1, 2, 3, 4, 5, 6],
                source_adv_sid: AdvertisingSetId(1),
                broadcast_id: BroadcastId(0x11),
                pa_sync_state: PaSyncState::Synced,
                big_encryption: EncryptionStatus::BroadcastCodeRequired,
                subgroups: vec![BigSubgroup::new(None)],
            }),
        );

        // Default PA interval value and subgroups value read from the BRS
        // characteristic are used.
        #[rustfmt::skip]
        fake_peer_service.expect_characteristic_value(
            &AUDIO_SCAN_CONTROL_POINT_HANDLE,
            vec![
                0x03, 0x11, 0x00,                    // opcode, source id, pa sync
                0xFF, 0xFF, 0x02,                    // pa sync, pa interval, num of subgroups
                0x17, 0x00, 0x00, 0x00,              // bis sync (0th subgroup)
                0x02, 0x01, 0x09,                    // metadata len, metadata
                0xFF, 0xFF, 0xFF, 0xFF,              // bis sync (1th subgroup)
                0x05, 0x04, 0x04, 0x65, 0x6E, 0x67,  // metadata len, metadata
            ],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let op_fut = client.modify_broadcast_source(
            BroadcastId(0x11),
            PaSync::DoNotSync,
            None,
            Some(HashSet::from([(0, 1), (0, 2), (0, 3), (0, 5)])),
            Some(HashMap::from([
                (0, vec![Metadata::BroadcastAudioImmediateRenderingFlag]),
                (1, vec![Metadata::Language("eng".to_string())]),
                (5, vec![Metadata::ProgramInfoURI("this subgroup shouldn't be added".to_string())]),
            ])),
        );
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn modify_broadcast_source_fail() {
        let (mut client, _fake_peer_service) = setup_client();

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        // Broadcast source wasn't previously added.
        let op_fut =
            client.modify_broadcast_source(BroadcastId(0x11), PaSync::DoNotSync, None, None, None);
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Err(_)));
    }

    #[test]
    fn remove_broadcast_source() {
        let (mut client, mut fake_peer_service) = setup_client();

        // Manually update the broadcast source tracker for testing purposes.
        // In practice, this would have been updated from BRS value change notification.
        client.broadcast_sources.lock().update_state(
            RECEIVE_STATE_1_HANDLE,
            BroadcastReceiveState::NonEmpty(ReceiveState {
                source_id: 0x11,
                source_address_type: AddressType::Public,
                source_address: [1, 2, 3, 4, 5, 6],
                source_adv_sid: AdvertisingSetId(1),
                broadcast_id: BroadcastId(0x11),
                pa_sync_state: PaSyncState::Synced,
                big_encryption: EncryptionStatus::BroadcastCodeRequired,
                subgroups: vec![],
            }),
        );

        fake_peer_service
            .expect_characteristic_value(&AUDIO_SCAN_CONTROL_POINT_HANDLE, vec![0x05, 0x11]);

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        // Broadcast source wasn't previously added.
        let op_fut = client.remove_broadcast_source(BroadcastId(0x11));
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn remove_broadcast_source_fail() {
        let (mut client, _fake_peer_service) = setup_client();

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        // Broadcast source wasn't previously added.
        let op_fut = client.remove_broadcast_source(BroadcastId(0x11));
        pin_mut!(op_fut);
        let polled = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Err(_)));
    }

    #[test]
    fn set_broadcast_code() {
        let (mut client, mut fake_peer_service) = setup_client();

        // Manually update the broadcast source tracker for testing purposes.
        // In practice, this would have been updated from BRS value change notification.
        client.broadcast_sources.lock().update_state(
            RECEIVE_STATE_1_HANDLE,
            BroadcastReceiveState::NonEmpty(ReceiveState {
                source_id: 0x01,
                source_address_type: AddressType::Public,
                source_address: [1, 2, 3, 4, 5, 6],
                source_adv_sid: AdvertisingSetId(1),
                broadcast_id: BroadcastId(0x030201),
                pa_sync_state: PaSyncState::Synced,
                big_encryption: EncryptionStatus::BroadcastCodeRequired,
                subgroups: vec![],
            }),
        );

        fake_peer_service.expect_characteristic_value(
            &AUDIO_SCAN_CONTROL_POINT_HANDLE,
            vec![0x04, 0x01, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        );

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let set_code_fut = client.set_broadcast_code(BroadcastId(0x030201), [1; 16]);
        pin_mut!(set_code_fut);
        let polled = set_code_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn set_broadcast_code_fails() {
        let (mut client, _) = setup_client();

        let mut noop_cx = futures::task::Context::from_waker(futures::task::noop_waker_ref());
        let set_code_fut = client.set_broadcast_code(BroadcastId(0x030201), [1; 16]);
        pin_mut!(set_code_fut);
        let polled = set_code_fut.poll_unpin(&mut noop_cx);

        // Should fail because we cannot get source id for the broadcast id since BRS
        // Characteristic value wasn't updated.
        assert_matches!(polled, Poll::Ready(Err(_)));
    }
}
