// 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;
use std::sync::Arc;

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

use bt_bap::types::{BroadcastCode, BroadcastId};
use bt_common::core::{Address, AddressType, AdvertisingSetId, PeriodicAdvertisingInterval};
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;

/// 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: Arc<Mutex<HashMap<SourceId, BroadcastCode>>>,
    // 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: Arc::new(Mutex::new(HashMap::new())),
            notification_streams: Some(SelectAll::new()),
        }
    }

    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?;
        log::debug!(
            "BASS client initialized: control point handle={:?}, {} BRS characteristic(s)",
            bascp_handle,
            brs_chars.len()
        );
        log::trace!("Discovered BRS characteristics: {:?}", brs_chars);
        let mut c = Self {
            gatt_client,
            audio_scan_control_point: bascp_handle,
            broadcast_sources: Arc::new(Mutex::new(KnownBroadcastSources::new(brs_chars))),
            broadcast_codes: Arc::new(Mutex::new(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]).0 {
                    Ok(decoded) => {
                        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(&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(&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(
        &self,
        broadcast_id: BroadcastId,
        address_type: AddressType,
        advertiser_address: Address,
        sid: AdvertisingSetId,
        pa_sync: PaSync,
        pa_interval: PeriodicAdvertisingInterval,
        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 Scan Delegator to modify a Broadcast Source's
    /// synchronization state and/or metadata.
    ///
    /// This method writes a **Modify Source** operation to the Broadcast Audio
    /// Scan Control Point. It reads the current state of the Broadcast
    /// Source from the local cache (the BRS characteristic value), applies
    /// the requested modifications, and sends the complete updated subgroup
    /// list to the server.
    ///
    /// # 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_map` - desired BIG to BIS synchronization update information. If
    ///   a BIG does not exist as a key, sync for that BIG is 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(
        &self,
        broadcast_id: BroadcastId,
        pa_sync: PaSync,
        pa_interval: Option<PeriodicAdvertisingInterval>,
        bis_map: HashMap<SubgroupIndex, BisSync>,
        metadata_map: Option<HashMap<SubgroupIndex, Vec<Metadata>>>,
    ) -> Result<(), Error> {
        let mut state = self
            .get_broadcast_source_state(&broadcast_id)
            .ok_or(Error::UnknownBroadcastSource(broadcast_id))?;

        // 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);
            }
        }

        // Update BIS_Sync param for BIGs if applicable.
        for (big_index, group) in state.subgroups.iter_mut().enumerate() {
            if let Some(bis_sync) = bis_map.get(&(big_index as u8)) {
                group.bis_sync = bis_sync.clone();
            }
        }

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

    pub async fn remove_broadcast_source(&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(
        &self,
        broadcast_id: BroadcastId,
        broadcast_code: BroadcastCode,
    ) -> Result<(), Error> {
        let source_id = self.get_source_id(&broadcast_id)?;

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

        // Save the broadcast code we sent.
        self.broadcast_codes.lock().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
    }

    /// Returns the handle of the Broadcast Audio Scan Control Point
    /// characteristic.
    pub fn audio_scan_control_point(&self) -> Handle {
        self.audio_scan_control_point
    }

    /// Looks up the Source ID assigned to a Broadcast ID if known.
    pub fn source_id(&self, broadcast_id: &BroadcastId) -> Option<SourceId> {
        self.broadcast_sources.lock().source_id(broadcast_id)
    }

    #[cfg(any(test, feature = "test-utils"))]
    pub fn insert_broadcast_receive_state(&mut self, handle: Handle, brs: BroadcastReceiveState) {
        self.broadcast_sources.lock().update_state(handle, 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::BROADCAST_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::BROADCAST_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::BROADCAST_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: RANDOME_CHAR_HANDLE,
                uuid: Uuid::from_u16(0x1234),
                properties: CharacteristicProperty::Notify.into(),
                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: CharacteristicProperty::Broadcast.into(),
                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::BROADCAST_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: CharacteristicProperty::Broadcast.into(),
                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::BROADCAST_NOTIFY,
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(2),
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperty::Broadcast.into(),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(3),
                uuid: BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID,
                properties: CharacteristicProperty::Broadcast.into(),
                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::BROADCAST_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::try_from(0x040302).unwrap(),
                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::BROADCAST_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::try_from(0x050403).unwrap(),
                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 (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 (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 (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::try_from(0x11).unwrap(),
            AddressType::Public,
            Address::new([0x04, 0x10, 0x00, 0x00, 0x00, 0x00]),
            AdvertisingSetId::try_from(1).unwrap(),
            PaSync::DoNotSync,
            PeriodicAdvertisingInterval::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 (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: Address::new([1, 2, 3, 4, 5, 6]),
                source_adv_sid: AdvertisingSetId::try_from(1).unwrap(),
                broadcast_id: BroadcastId::try_from(0x11).unwrap(),
                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::try_from(0x11).unwrap(),
            PaSync::DoNotSync,
            Some(PeriodicAdvertisingInterval(0xAAAA)),
            HashMap::new(),
            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 (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: Address::new([1, 2, 3, 4, 5, 6]),
                source_adv_sid: AdvertisingSetId::try_from(1).unwrap(),
                broadcast_id: BroadcastId::try_from(0x11).unwrap(),
                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
                0x15, 0x00, 0x00, 0x00,              // bis sync (0th subgroup)
                0x02, 0x01, 0x09,                    // metadata len, metadata
                0xFF, 0xFF, 0xFF, 0xFF,              // bis sync (1st 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::try_from(0x11).unwrap(),
            PaSync::DoNotSync,
            None,
            HashMap::from([(0, BisSync::sync(vec![1, 3, 5]).unwrap())]),
            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: Poll<Result<(), Error>> = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

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

        client.broadcast_sources.lock().update_state(
            RECEIVE_STATE_1_HANDLE,
            BroadcastReceiveState::NonEmpty(ReceiveState {
                source_id: 0x11,
                source_address_type: AddressType::Public,
                source_address: Address::new([1, 2, 3, 4, 5, 6]),
                source_adv_sid: AdvertisingSetId::try_from(1).unwrap(),
                broadcast_id: BroadcastId::try_from(0x11).unwrap(),
                pa_sync_state: PaSyncState::Synced,
                big_encryption: EncryptionStatus::BroadcastCodeRequired,
                subgroups: vec![BigSubgroup::new(None)],
            }),
        );

        #[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
                0x15, 0x00, 0x00, 0x00,              // bis sync (0th subgroup)
                0x02, 0x01, 0x09,                    // metadata len, metadata
                0x0A, 0x00, 0x00, 0x00,              // bis sync for 1st subgroup (BIS index 2 and 4 = 0b00001010)
                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::try_from(0x11).unwrap(),
            PaSync::DoNotSync,
            None,
            HashMap::from([
                (0, BisSync::sync(vec![1, 3, 5]).unwrap()),
                (1, BisSync::sync(vec![2, 4]).unwrap()),
            ]),
            Some(HashMap::from([
                (0, vec![Metadata::BroadcastAudioImmediateRenderingFlag]),
                (1, vec![Metadata::Language("eng".to_string())]),
            ])),
        );
        pin_mut!(op_fut);
        let polled: Poll<Result<(), Error>> = op_fut.poll_unpin(&mut noop_cx);
        assert_matches!(polled, Poll::Ready(Ok(_)));
    }

    #[test]
    fn modify_broadcast_source_fail() {
        let (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::try_from(0x11).unwrap(),
            PaSync::DoNotSync,
            None,
            HashMap::new(),
            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 (client, mut fake_peer_service) = setup_client();
        let bid = BroadcastId::try_from(0x11).expect("should not fail");

        // 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: Address::new([1, 2, 3, 4, 5, 6]),
                source_adv_sid: AdvertisingSetId::try_from(1).unwrap(),
                broadcast_id: bid,
                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(bid);
        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 (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::try_from(0x11).unwrap());
        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 (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: Address::new([1, 2, 3, 4, 5, 6]),
                source_adv_sid: AdvertisingSetId::try_from(1).unwrap(),
                broadcast_id: BroadcastId::try_from(0x030201).unwrap(),
                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::try_from(0x030201).unwrap(),
            BroadcastCode::new([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 (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::try_from(0x030201).unwrap(),
            BroadcastCode::new([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(_)));
    }
}
