// 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::time::SystemTime;
use std::sync::{Arc, RwLock};

use futures::Stream;
use tracing::warn;

use bt_common::packet_encoding::Decodable;
use bt_gatt::types::{Handle, Result as GattResult};
use bt_gatt::client::{CharacteristicNotification, PeerService, ServiceCharacteristic};

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<PeerServiceT, GattNotificationStream> {
    gatt_client: Box<PeerServiceT>,
    /// 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<GattNotificationStream>,
}

#[allow(dead_code)]
impl<GattNotificationStream: Stream<Item = GattResult<CharacteristicNotification>>, PeerServiceT: PeerService<NotificationStream = GattNotificationStream>> BroadcastAudioScanServiceClient<PeerServiceT, GattNotificationStream> {
    async fn create(gatt_client: Box<PeerServiceT>) -> 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: &PeerServiceT) -> Result<(Handle, HashMap<Handle, Option<ReceiveStateReadValue>>), Error> {
        let bascp = ServiceCharacteristic::find(gatt_client, BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID).await.map_err(|e| Error::Gatt(e))?;
        let brs = ServiceCharacteristic::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::{FutureExt, pin_mut};

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

    #[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::create(Box::new(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::create(Box::new(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::create(Box::new(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::create(Box::new(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");
        };
    }
}
