// Copyright 2023 Google LLC
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub mod error;

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::time::SystemTime;

use tracing::warn;

use bt_common::packet_encoding::Decodable;
use bt_gatt::client::{PeerService, ServiceCharacteristic};
use bt_gatt::types::Handle;

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

const READ_CHARACTERISTIC_BUFFER_SIZE: usize = 255;

#[allow(dead_code)]
type ReceiveStateReadValue = (BroadcastReceiveState, SystemTime);

/// Manages connection to the Broadcast Audio Scan Service at the
/// remote Scan Delegator and writes/reads characteristics to/from it.
#[allow(dead_code)]
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.
    receive_states: Arc<RwLock<HashMap<Handle, Option<ReceiveStateReadValue>>>>,
    // List of characteristic notification streams we are listening to.
    notification_streams: Vec<T::NotificationStream>,
}

#[allow(dead_code)]
impl<T: bt_gatt::GattTypes> BroadcastAudioScanServiceClient<T> {
    async fn create(gatt_client: T::PeerService) -> Result<Self, Error> {
        let characteristics = Self::discover_all_characteristics(&gatt_client).await?;
        let mut client = Self {
            gatt_client,
            audio_scan_control_point: characteristics.0,
            receive_states: Arc::new(RwLock::new(characteristics.1)),
            notification_streams: Vec::new(),
        };
        client.register_notification().await?;
        Ok(client)
    }

    // Discover all the characteristics that are required.
    // On success, returns the tuple of (Broadcast Audio Scan Control Point
    // Characteristic, HashMap of all Broadcast Received State Characteristics).
    async fn discover_all_characteristics(
        gatt_client: &T::PeerService,
    ) -> Result<(Handle, HashMap<Handle, Option<ReceiveStateReadValue>>), Error> {
        let bascp =
            ServiceCharacteristic::<T>::find(gatt_client, BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID)
                .await
                .map_err(|e| Error::Gatt(e))?;
        let brs = ServiceCharacteristic::<T>::find(gatt_client, BROADCAST_RECEIVE_STATE_UUID)
            .await
            .map_err(|e| Error::Gatt(e))?;
        if bascp.len() == 0 || brs.len() == 0 {
            return Err(Error::Service(ServiceError::MissingCharacteristic));
        }
        if bascp.len() > 1 {
            return Err(Error::Service(ServiceError::ExtraScanControlPointCharacteristic));
        }
        // Discover all characteristics at the BASS at the remote peer over the GATT
        // connection. Service should have a single Broadcast Audio Scan Control Point
        // Characteristic
        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) => {
                        brs_map.insert(*c.handle(), Some((decoded.0, SystemTime::now())));
                        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(), None);
        }
        Ok((*bascp[0].handle(), brs_map))
    }

    /// Registers for notifications for Broadcast Receive State characteristics.
    async fn register_notification(&mut self) -> Result<(), Error> {
        // Notification is mandatory for Receive State as per BASS v1.0 Section 3.2.1.
        let lock = self.receive_states.write().unwrap();
        for handle in lock.keys() {
            let stream = self.gatt_client.subscribe(handle);
            self.notification_streams.push(stream);
        }
        Ok(())
    }
}

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

    use std::task::Poll;

    use futures::{pin_mut, FutureExt};

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

    #[test]
    fn create_client() {
        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: 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_RECEIVE_STATE_UUID,
                properties: CharacteristicProperties(vec![
                    CharacteristicProperty::Broadcast,
                    CharacteristicProperty::Notify,
                ]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(3),
                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(4),
                uuid: Uuid::from_u16(0x1234),
                properties: CharacteristicProperties(vec![CharacteristicProperty::Notify]),
                permissions: AttributePermissions::default(),
                descriptors: vec![],
            },
            vec![],
        );
        fake_peer_service.add_characteristic(
            Characteristic {
                handle: Handle(5),
                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 BASSClient to be succesfully created");
        };

        // Check that all the characteristics have been discovered.
        assert_eq!(client.audio_scan_control_point, Handle(5));
        let broadcast_receive_states = client.receive_states.read().unwrap();
        assert!(broadcast_receive_states.contains_key(&Handle(1)));
        assert!(broadcast_receive_states.contains_key(&Handle(2)));
        assert!(broadcast_receive_states.contains_key(&Handle(3)));

        // Three notification one for each of broadcast receive state characteristic
        // should have been set up.
        assert_eq!(client.notification_streams.len(), 3);
    }

    #[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 BASSClient 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 BASSClient 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 BASSClient to have failed");
        };
    }
}
