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

use bt_common::core::CodecId;
use bt_common::generic_audio::metadata_ltv::Metadata;
use bt_common::{PeerId, Uuid};
use bt_gatt::connected_isochronous::{CigId, CisId, Framing, MaxTransportLatency};
use bt_gatt::server::{LocalService, Server, ServiceDefinition, ServiceId};
use bt_gatt::server::{ReadResponder, WriteResponder};
use bt_gatt::types::{
    AttributePermissions, CharacteristicProperties, GattError, Handle, SecurityLevels,
};
use bt_gatt::Characteristic;

use futures::channel::oneshot::{self, Canceled};
use futures::stream::{FusedStream, FuturesUnordered};
use futures::task::{Poll, Waker};
use futures::{Future, Stream, StreamExt};
use pin_project::pin_project;
use std::collections::{HashMap, VecDeque};

use crate::types::*;

#[derive(Debug, thiserror::Error)]
pub enum ServerError {
    #[error("Server Only Operation")]
    ServerOnlyOperation,
    #[error("Service is already published")]
    AlreadyPublished,
    #[error("Issue publishing service: {0}")]
    PublishError(#[from] bt_gatt::types::Error),
    #[error("Unknown Peer: {0}")]
    UnknownPeer(bt_common::PeerId),
}

#[pin_project(project = LocalServiceProj)]
enum LocalServiceState<T: bt_gatt::ServerTypes> {
    NotPublished {
        waker: Option<Waker>,
    },
    Preparing {
        #[pin]
        fut: T::LocalServiceFut,
    },
    Published {
        service: T::LocalService,
        #[pin]
        events: T::ServiceEventStream,
    },
    Terminated,
}

impl<T: bt_gatt::ServerTypes> Default for LocalServiceState<T> {
    fn default() -> Self {
        Self::NotPublished { waker: None }
    }
}

impl<T: bt_gatt::ServerTypes> LocalServiceState<T> {
    fn service(&self) -> Option<&T::LocalService> {
        let Self::Published { service, .. } = self else {
            return None;
        };
        Some(service)
    }

    fn notify(&self, characteristic: &Handle, data: &[u8], peers: &[PeerId]) -> bool {
        let Some(service) = self.service() else {
            return false;
        };
        service.notify(characteristic, data, peers);
        true
    }
}

impl<T: bt_gatt::ServerTypes> Stream for LocalServiceState<T> {
    type Item = Result<bt_gatt::server::ServiceEvent<T>, Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        // SAFETY:
        //  - Wakers are Unpin
        //  - We re-pin the structurally pinned futures in Preparing and Published
        //    (service is untouched)
        //  - Terminated is empty
        loop {
            match self.as_mut().project() {
                LocalServiceProj::Terminated => return Poll::Ready(None),
                LocalServiceProj::NotPublished { .. } => {
                    self.as_mut()
                        .set(LocalServiceState::NotPublished { waker: Some(cx.waker().clone()) });
                    return Poll::Pending;
                }
                LocalServiceProj::Preparing { fut } => {
                    let service_result = futures::ready!(fut.poll(cx));
                    let Ok(service) = service_result else {
                        self.as_mut().set(LocalServiceState::Terminated);
                        return Poll::Ready(Some(Err(Error::from(ServerError::PublishError(
                            service_result.err().unwrap(),
                        )))));
                    };
                    let events = service.publish();
                    self.as_mut().set(LocalServiceState::Published { service, events });
                    continue;
                }
                LocalServiceProj::Published { service: _, events } => {
                    let item = futures::ready!(events.poll_next(cx));
                    let Some(gatt_result) = item else {
                        self.as_mut().set(LocalServiceState::Terminated);
                        return Poll::Ready(Some(Err(Error::from(ServerError::PublishError(
                            "GATT server terminated".into(),
                        )))));
                    };
                    let Ok(event) = gatt_result else {
                        self.as_mut().set(LocalServiceState::Terminated);
                        return Poll::Ready(Some(Err(Error::from(ServerError::PublishError(
                            gatt_result.err().unwrap(),
                        )))));
                    };
                    return Poll::Ready(Some(Ok(event)));
                }
            }
        }
    }
}

impl<T: bt_gatt::ServerTypes> FusedStream for LocalServiceState<T> {
    fn is_terminated(&self) -> bool {
        match self {
            Self::Terminated => true,
            _ => false,
        }
    }
}

impl<T: bt_gatt::ServerTypes> LocalServiceState<T> {
    fn is_not_published(&self) -> bool {
        matches!(self, LocalServiceState::NotPublished { .. })
    }
}

#[derive(Debug, Clone)]
struct AseControlOperationAction {
    peer_id: PeerId,
    opcode: Option<AseControlPointOpcode>,
    response_codes: Vec<ResponseCode>,
    new_endpoints: Vec<AudioStreamEndpoint>,
}

impl AseControlOperationAction {
    fn notify_control_point_value(&self) -> Option<Vec<u8>> {
        if self.opcode.is_none() || self.response_codes.is_empty() {
            return None;
        }
        use bt_common::packet_encoding::Encodable;

        let opcode = self.opcode.unwrap().into();
        let notification = if let ResponseCode::InvalidLength { .. }
        | ResponseCode::UnsupportedOpcode { .. } = self.response_codes[0]
        {
            ControlPointNotification::new_error(opcode, self.response_codes[0].to_code())
        } else {
            let mut cp_notification = ControlPointNotification::new(opcode);
            for response in &self.response_codes {
                cp_notification.add_response(response.clone());
            }
            cp_notification
        };
        let mut buf = vec![0; notification.encoded_len()];
        notification.encode(&mut buf).unwrap();
        Some(buf)
    }
}

struct AseControlOperationFut {
    peer_id: PeerId,
    /// The opcode of the operation that this future is for, if there is one.
    opcode: Option<AseControlPointOpcode>,
    /// The current set of response codes gathered for this operation.
    /// Empty if there are no responses to send.
    current_response_codes: Vec<ResponseCode>,
    /// New Endpoint States after the operation is complete
    endpoints: Vec<AudioStreamEndpoint>,
    /// Queue of responses we are still waiting on from the operation.
    waiting: FuturesUnordered<
        futures::channel::oneshot::Receiver<Result<AudioStreamEndpoint, ResponseCode>>,
    >,
}

impl From<&AseControlOperationFut> for AseControlOperationAction {
    fn from(value: &AseControlOperationFut) -> Self {
        Self {
            peer_id: value.peer_id,
            opcode: value.opcode,
            response_codes: value.current_response_codes.clone(),
            new_endpoints: value.endpoints.clone(),
        }
    }
}

impl Future for AseControlOperationFut {
    type Output = AseControlOperationAction;

    fn poll(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> Poll<Self::Output> {
        loop {
            if self.waiting.is_terminated() {
                let this = std::pin::Pin::into_inner(self);
                return Poll::Ready((&*this).into());
            }
            let update = futures::ready!(self.waiting.poll_next_unpin(cx));
            match update {
                None => continue,
                Some(Err(Canceled)) => {
                    log::warn!("Detected dropped responder!");
                    // TODO: maybe figure out how to determine which AseId got canceled here
                    self.current_response_codes
                        .push(ResponseCode::UnspecifiedError { ase_id: AseId(0x00) });
                    // Bail on the rest of them.
                    self.waiting.clear();
                }
                Some(Ok(Ok(endpoint))) => {
                    self.current_response_codes
                        .push(ResponseCode::Success { ase_id: endpoint.ase_id });
                    self.endpoints.push(endpoint);
                }
                Some(Ok(Err(response_code))) => self.current_response_codes.push(response_code),
            }
        }
    }
}

#[pin_project]
pub struct AudioStreamControlServiceServer<T: bt_gatt::ServerTypes> {
    service_def: ServiceDefinition,
    #[pin]
    local_service: LocalServiceState<T>,
    default_client_endpoints: ClientEndpoints,
    client_endpoints: HashMap<PeerId, ClientEndpoints>,
    outgoing_events: VecDeque<ServiceEvent>,
    // TODO: maybe these should be FuturesOrdered if the operations should be FIFOed
    // Not pinned as AseControlOperationFut is Unpin.
    responses: futures::stream::FuturesUnordered<AseControlOperationFut>,
}

const CONTROL_POINT_HANDLE: Handle = Handle(1);
const BASE_ENDPOINT_HANDLE: Handle = Handle(2);

pub const ASCS_UUID: Uuid = Uuid::from_u16(0x184E);

// As only one ASCS service is allowed on a host, define an arbitrary ServiceId
// that every AudioStreamControlServiceServer will attempt to use so publishing
// multiple will fail.
pub(crate) const ASCS_SERVICE_ID: ServiceId = ServiceId::new(1123901);

impl<T: bt_gatt::ServerTypes> AudioStreamControlServiceServer<T> {
    pub fn new(source_count: u8, sink_count: u8) -> Self {
        let default_client_endpoints = ClientEndpoints::new(source_count, sink_count);
        let mut chars: Vec<Characteristic> = (&default_client_endpoints).into();
        chars.push(Self::build_control_point());
        let mut service_def = ServiceDefinition::new(
            ASCS_SERVICE_ID,
            ASCS_UUID,
            bt_gatt::types::ServiceKind::Primary,
        );
        for c in chars {
            service_def.add_characteristic(c).unwrap();
        }
        Self {
            service_def,
            local_service: Default::default(),
            default_client_endpoints,
            client_endpoints: Default::default(),
            outgoing_events: VecDeque::new(),
            responses: FuturesUnordered::new(),
        }
    }

    fn build_control_point() -> Characteristic {
        let properties = CharacteristicProperties::WRITE_NOTIFY;
        let permissions =
            AttributePermissions::with_levels(&properties, &SecurityLevels::encryption_required());
        Characteristic {
            handle: CONTROL_POINT_HANDLE,
            uuid: Uuid::from_u16(0x2BC6),
            properties,
            permissions,
            descriptors: Vec::new(),
        }
    }

    pub fn publish(&mut self, server: &T::Server) -> Result<(), Error> {
        if !self.local_service.is_not_published() {
            return Err(Error::from(ServerError::AlreadyPublished));
        }
        let LocalServiceState::NotPublished { waker } = std::mem::replace(
            &mut self.local_service,
            LocalServiceState::Preparing { fut: server.prepare(self.service_def.clone()) },
        ) else {
            unreachable!();
        };
        waker.map(Waker::wake);
        Ok(())
    }

    pub fn cis_established(
        &mut self,
        peer_id: PeerId,
        ase_id: AseId,
        cis: (CigId, CisId),
    ) -> Result<(), Error> {
        let endpoints = self
            .client_endpoints
            .get_mut(&peer_id)
            .ok_or(Error::from(ServerError::UnknownPeer(peer_id)))?;
        endpoints.established_cis(ase_id, cis);
        for operation in endpoints.autonomous_operations() {
            self.queue_operation_unpin(peer_id, operation);
        }
        Ok(())
    }

    pub fn cis_released(
        &mut self,
        peer_id: PeerId,
        ase_id: AseId,
        cis: (CigId, CisId),
    ) -> Result<(), Error> {
        let endpoints = self
            .client_endpoints
            .get_mut(&peer_id)
            .ok_or(Error::from(ServerError::UnknownPeer(peer_id)))?;
        endpoints.released_cis(ase_id, cis);
        for operation in endpoints.autonomous_operations() {
            self.queue_operation_unpin(peer_id, operation);
        }
        Ok(())
    }

    fn queue_operation_unpin(&mut self, peer_id: PeerId, op: AseControlOperation) {
        let (events, fut) =
            op.apply(peer_id, self.client_endpoints.get(&peer_id).unwrap().endpoints.clone());
        self.outgoing_events.extend(events);
        self.responses.push(fut);
    }

    fn queue_operation(self: std::pin::Pin<&mut Self>, peer_id: PeerId, op: AseControlOperation) {
        let this = self.project();
        let (events, fut) =
            op.apply(peer_id, this.client_endpoints.get(&peer_id).unwrap().endpoints.clone());
        this.outgoing_events.extend(events);
        this.responses.push(fut);
    }

    /// Applies operations that are ready to complete (all outstanding events
    /// have been responded to)
    fn poll_operations(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) {
        let this = self.project();
        loop {
            let Poll::Ready(Some(operation)) = this.responses.poll_next_unpin(cx) else {
                return;
            };
            if let Some(notification) = operation.notify_control_point_value() {
                this.local_service.notify(
                    &CONTROL_POINT_HANDLE,
                    &notification,
                    &[operation.peer_id],
                );
            }
            if operation.new_endpoints.is_empty() {
                return;
            }
            // Apply the endpoint changes, and notify each endpoint
            let Some(current_endpoints) = this.client_endpoints.get_mut(&operation.peer_id) else {
                log::warn!(
                    "PeerId {peer_id} has disppeared while an operation was happening, ignoring..",
                    peer_id = operation.peer_id
                );
                continue;
            };
            for endpoint in operation.new_endpoints {
                this.local_service.notify(
                    &endpoint.handle,
                    endpoint.into_char_value().as_slice(),
                    &[operation.peer_id],
                );
                let _ = current_endpoints.endpoints.insert(endpoint.ase_id, endpoint);
            }
        }
    }
}

impl From<&AudioStreamEndpoint> for Characteristic {
    fn from(value: &AudioStreamEndpoint) -> Self {
        let properties = CharacteristicProperties::READ_NOTIFY;
        let permissions =
            AttributePermissions::with_levels(&properties, &SecurityLevels::encryption_required());
        Characteristic {
            handle: value.handle,
            uuid: (&value.direction).into(),
            properties,
            permissions,
            descriptors: Vec::new(),
        }
    }
}

struct ClientEndpoints {
    endpoints: HashMap<AseId, AudioStreamEndpoint>,
    handles: HashMap<Handle, AseId>,
    established: HashMap<AseId, Vec<(CigId, CisId)>>,
}

impl ClientEndpoints {
    fn new(source_count: u8, sink_count: u8) -> Self {
        let dir_iter = std::iter::repeat(AudioDirection::Source)
            .take(source_count as usize)
            .chain(std::iter::repeat(AudioDirection::Sink).take(sink_count as usize));
        // AseIds shall not have an id of 0
        let (endpoints, handles) = (1..)
            .zip(dir_iter)
            .map(|(raw_ase_id, direction)| {
                let handle = Handle(BASE_ENDPOINT_HANDLE.0 + raw_ase_id as u64);
                let ase_id = AseId(raw_ase_id);
                (
                    (
                        ase_id,
                        AudioStreamEndpoint {
                            handle,
                            ase_id,
                            direction,
                            state: AseState::Idle,
                            additional: AseAdditionalParameters::None,
                        },
                    ),
                    (handle, ase_id),
                )
            })
            .unzip();
        Self { endpoints, handles, established: Default::default() }
    }

    fn clone_for_peer(&self, _peer_id: PeerId) -> Self {
        // TODO: Randomize the ASE_IDs.  Handles need to stay the same.
        Self {
            endpoints: self.endpoints.clone(),
            handles: self.handles.clone(),
            established: Default::default(),
        }
    }

    fn established_cis(&mut self, ase_id: AseId, cis: (CigId, CisId)) {
        self.established.entry(ase_id).or_default().push(cis);
    }

    fn released_cis(&mut self, ase_id: AseId, cis: (CigId, CisId)) {
        self.established.get_mut(&ase_id).map(|established| established.retain(|i| i != &cis));
    }

    fn autonomous_operations(&self) -> Vec<AseControlOperation> {
        let mut operations = Vec::new();
        for endpoint in self.endpoints.values() {
            match endpoint.state {
                AseState::Enabling
                    if self.established.get(&endpoint.ase_id).is_some_and(|e| !e.is_empty()) =>
                {
                    operations.push(AseControlOperation::ReceiverStartReady {
                        ases: vec![endpoint.ase_id],
                    });
                }
                AseState::Releasing
                    if self.established.get(&endpoint.ase_id).is_some_and(|e| e.is_empty()) =>
                {
                    operations.push(AseControlOperation::Released { ase_id: endpoint.ase_id });
                }
                _ => continue,
            }
        }
        operations
    }
}

impl From<&ClientEndpoints> for Vec<Characteristic> {
    fn from(value: &ClientEndpoints) -> Self {
        value.endpoints.values().map(Into::into).collect()
    }
}

#[derive(Debug)]
pub struct CodecConfigureResponder {
    endpoint: AudioStreamEndpoint,
    codec_id: CodecId,
    codec_config: Vec<u8>,
    sender: futures::channel::oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
}

impl CodecConfigureResponder {
    pub fn reject(self, err: ResponseCode) {
        let _ = self.sender.send(Err(err));
    }

    pub fn accept(
        mut self,
        framing: Framing,
        preferred_phys: Vec<Phy>,
        preferred_retransmission_number: u8,
        max_transport_latency: MaxTransportLatency,
        presentation_delay_range: PresentationDelayRange,
    ) {
        self.endpoint.state = AseState::CodecConfigured;
        self.endpoint.additional = AseAdditionalParameters::CodecConfigured {
            framing,
            preferred_phys,
            preferred_retransmission_number,
            max_transport_latency,
            presentation_delay_range,
            codec_id: self.codec_id,
            codec_config: self.codec_config,
        };
        let _ = self.sender.send(Ok(self.endpoint));
    }
}

#[derive(Debug)]
pub struct QosConfigureResponder {
    endpoint: AudioStreamEndpoint,
    configuration: QosConfiguration,
    sender: futures::channel::oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
}

impl QosConfigureResponder {
    pub fn reject(self, err: ResponseCode) {
        let _ = self.sender.send(Err(err));
    }

    pub fn accept(mut self) {
        self.endpoint.state = AseState::QosConfigured;
        self.endpoint.additional = self.configuration.into();
        let _ = self.sender.send(Ok(self.endpoint));
    }
}

#[derive(Debug)]
pub struct EnableResponder {
    endpoint: AudioStreamEndpoint,
    metadata: Vec<Metadata>,
    sender: futures::channel::oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
}

impl EnableResponder {
    pub fn reject(self, err: ResponseCode) {
        let _ = self.sender.send(Err(err));
    }

    pub fn accept(mut self) {
        let AseAdditionalParameters::QosConfigured { configuration, .. } = self.endpoint.additional
        else {
            // Shouldn't happen
            let _ = self
                .sender
                .send(Err(ResponseCode::UnspecifiedError { ase_id: self.endpoint.ase_id }));
            return;
        };
        self.endpoint.state = AseState::Enabling;
        self.endpoint.additional = AseAdditionalParameters::Streaming {
            cig_id: configuration.cig_id,
            cis_id: configuration.cis_id,
            metadata: self.metadata,
            qos_configured: Some(configuration),
        };
        let _ = self.sender.send(Ok(self.endpoint));
    }
}

#[derive(Debug)]
pub struct DisableResponder {
    endpoint: AudioStreamEndpoint,
    sender: futures::channel::oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
}

impl DisableResponder {
    pub fn reject(self, err: ResponseCode) {
        let _ = self.sender.send(Err(err));
    }

    pub fn accept(mut self) {
        let AseAdditionalParameters::Streaming { qos_configured: Some(qos_configured), .. } =
            self.endpoint.additional
        else {
            unreachable!();
        };
        self.endpoint.state = AseState::QosConfigured;
        self.endpoint.additional = qos_configured.into();
        let _ = self.sender.send(Ok(self.endpoint));
    }
}

#[derive(Debug)]
pub struct UpdateMetadataResponder {
    endpoint: AudioStreamEndpoint,
    metadata: Vec<Metadata>,
    sender: futures::channel::oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
}

impl UpdateMetadataResponder {
    pub fn reject(self, err: ResponseCode) {
        let _ = self.sender.send(Err(err));
    }

    pub fn accept(mut self) {
        let AseAdditionalParameters::Streaming { metadata, .. } = &mut self.endpoint.additional
        else {
            unreachable!();
        };
        *metadata = self.metadata;
        let _ = self.sender.send(Ok(self.endpoint));
    }
}

#[derive(Debug)]
pub enum ServiceEvent {
    CodecConfigure {
        configuration: CodecConfiguration,
        responder: CodecConfigureResponder,
    },
    QosConfigure {
        /// Peer configuring this stream
        peer_id: PeerId,
        /// Stream ID of the stream being configured
        /// This ID is unique to the peer
        // TODO: Consider replacing with source or sink, AseId should map to (Peer, Cig, Cis) at
        // this point
        target_configuration: QosConfiguration,
        responder: QosConfigureResponder,
    },
    Enable {
        /// Peer enabling this stream
        peer_id: PeerId,
        /// Stream ID of the stream being configured
        ase_id: AseId,
        /// Stream that this is being tied to.
        /// This CIS may already be established after QosConfigure and will
        /// match the QosConfigured value.
        cis: (CigId, CisId),
        /// Additional Metadata provided
        /// Also available using
        /// AudioStreamControlServiceServer::get_metadata(peer_id, ase_id)
        metadata: Vec<Metadata>,
        /// Responder.  Responding positively to this will start streaming if
        /// the StreamEndpoint is a sink endpoint.  For a source
        /// endpoint, an additional Start event will be generated to
        /// indicate when the client is ready to receive data.
        responder: EnableResponder,
    },
    /// Ok to start streaming.
    /// Sent only for Source Endpoints.
    /// No responder, this event has already been accepted.
    Start {
        peer_id: PeerId,
        ase_id: AseId,
        cis: (CigId, CisId),
    },
    /// Disable this stream.
    /// Stop sending data on the CisId and CigId listed, or expect the client to
    /// stop sending audio data.
    Disable {
        /// Peer disabling this stream
        peer_id: PeerId,
        /// Stream ID of this stream
        ase_id: AseId,
        /// Isochronous Stream that was previously in use.
        cis: (CigId, CisId),
        /// Responder.  Responding positively will indicate to the client that
        /// data has ceased being sent.
        responder: DisableResponder,
    },
    /// Update Metadata
    UpdateMetadata {
        peer_id: PeerId,
        ase_id: AseId,
        metadata: Vec<Metadata>,
        responder: UpdateMetadataResponder,
    },
}

impl CodecConfiguration {
    fn into_event(
        self,
        endpoint: AudioStreamEndpoint,
        sender: oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
    ) -> crate::server::ServiceEvent {
        ServiceEvent::CodecConfigure {
            configuration: self.clone(),
            responder: crate::server::CodecConfigureResponder {
                endpoint,
                codec_id: self.codec_id,
                codec_config: self.codec_specific_configuration.clone(),
                sender,
            },
        }
    }
}

impl QosConfiguration {
    fn into_event(
        self,
        peer_id: PeerId,
        endpoint: AudioStreamEndpoint,
        sender: oneshot::Sender<Result<AudioStreamEndpoint, ResponseCode>>,
    ) -> crate::server::ServiceEvent {
        ServiceEvent::QosConfigure {
            peer_id,
            target_configuration: self.clone(),
            responder: crate::server::QosConfigureResponder {
                endpoint,
                configuration: self,
                sender,
            },
        }
    }
}

impl AseControlOperation {
    fn apply(
        self,
        peer_id: PeerId,
        endpoint_map: HashMap<AseId, AudioStreamEndpoint>,
    ) -> (Vec<crate::server::ServiceEvent>, AseControlOperationFut) {
        let mut current_response_codes = Vec::new();
        let mut waiting = Vec::new();
        let mut events: Vec<crate::server::ServiceEvent> = Vec::new();
        let mut endpoints = Vec::new();
        let opcode: Option<AseControlPointOpcode> = (&self).try_into().ok();
        match self {
            Self::ConfigCodec { codec_configurations, mut responses } => {
                current_response_codes.append(&mut responses);
                for codec_configuration in codec_configurations {
                    let ase_id = codec_configuration.ase_id;
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    let (send, recv) = oneshot::channel();
                    waiting.push(recv);
                    events.push(codec_configuration.into_event(endpoint.clone(), send));
                }
            }
            Self::ConfigQos { qos_configurations, mut responses } => {
                current_response_codes.append(&mut responses);
                for configuration in qos_configurations {
                    let ase_id = configuration.ase_id;
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    let (send, recv) = oneshot::channel();
                    waiting.push(recv);
                    events.push(configuration.into_event(peer_id, endpoint.clone(), send));
                }
            }
            Self::Enable { ases_with_metadata, mut responses } => {
                current_response_codes.append(&mut responses);
                for AseIdWithMetadata { ase_id, metadata } in ases_with_metadata {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    let (sender, recv) = oneshot::channel();
                    waiting.push(recv);
                    let cis = endpoint.get_cis().unwrap();
                    let event = ServiceEvent::Enable {
                        ase_id,
                        cis,
                        peer_id,
                        metadata: metadata.clone(),
                        responder: EnableResponder { endpoint: endpoint.clone(), metadata, sender },
                    };
                    events.push(event);
                }
            }
            Self::ReceiverStartReady { ases } => {
                for ase_id in ases {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    if endpoint.direction != AudioDirection::Source {
                        current_response_codes.push(ResponseCode::InvalidAseDirection { ase_id });
                        continue;
                    }
                    let cis = endpoint.get_cis().unwrap();
                    // Automatically accept.
                    let mut endpoint = endpoint.clone();
                    endpoint.state = AseState::Streaming;
                    endpoints.push(endpoint);
                    current_response_codes.push(ResponseCode::Success { ase_id });
                    events.push(ServiceEvent::Start { peer_id, ase_id, cis });
                }
            }
            Self::Disable { ases } => {
                for ase_id in ases {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    let AseAdditionalParameters::Streaming { cig_id, cis_id, .. } =
                        endpoint.additional
                    else {
                        unreachable!();
                    };
                    if endpoint.direction == AudioDirection::Source {
                        // Accept automatically, and wait for the ReceiverStopReady to send Disable
                        // event.
                        let mut endpoint = endpoint.clone();
                        endpoint.state = AseState::Disabling;
                        endpoints.push(endpoint);
                        current_response_codes.push(ResponseCode::Success { ase_id });
                        continue;
                    }
                    let (sender, recv) = oneshot::channel();
                    waiting.push(recv);
                    events.push(ServiceEvent::Disable {
                        peer_id,
                        ase_id,
                        cis: (cig_id, cis_id),
                        responder: DisableResponder { endpoint: endpoint.clone(), sender },
                    });
                }
            }
            Self::ReceiverStopReady { ases } => {
                for ase_id in ases {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    if endpoint.direction != AudioDirection::Source {
                        current_response_codes.push(ResponseCode::InvalidAseDirection { ase_id });
                        continue;
                    }
                    let AseAdditionalParameters::Streaming { cig_id, cis_id, .. } =
                        endpoint.additional
                    else {
                        unreachable!();
                    };
                    let (sender, recv) = oneshot::channel();
                    waiting.push(recv);
                    events.push(ServiceEvent::Disable {
                        peer_id,
                        ase_id,
                        cis: (cig_id, cis_id),
                        responder: DisableResponder { endpoint: endpoint.clone(), sender },
                    });
                }
            }
            Self::Release { ases } => {
                for ase_id in ases {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if !opcode.unwrap().allowed_in_state(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    // Automatically accept.  We will automatically perform the Released operation
                    // on the next poll.
                    let mut endpoint = endpoint.clone();
                    endpoint.state = AseState::Releasing;
                    endpoint.additional = AseAdditionalParameters::None;
                    current_response_codes.push(ResponseCode::Success { ase_id });
                    endpoints.push(endpoint);
                }
            }
            Self::Released { ase_id } => {
                // Should only happen when we detect a link loss and are told so by the client.
                // Therefore we can transition immediately.
                // If there is no endpoint by that ase_id, we do nothing.
                if let Some(mut endpoint) = endpoint_map.get(&ase_id).cloned() {
                    // TODO(b/433287917): implement caching with either preferred or cached
                    // configurations
                    endpoint.state = AseState::Idle;
                    endpoint.additional = AseAdditionalParameters::None;
                    endpoints.push(endpoint);
                } else {
                    log::warn!("Received Released for unknown endpoint: {ase_id:?}");
                }
            }
            Self::UpdateMetadata { ases_with_metadata, mut responses } => {
                current_response_codes.append(&mut responses);
                for AseIdWithMetadata { ase_id, metadata } in ases_with_metadata {
                    let Some(endpoint) = endpoint_map.get(&ase_id) else {
                        current_response_codes
                            .push(ResponseCode::InvalidAseId { value: ase_id.into() });
                        continue;
                    };
                    if ![AseState::Enabling, AseState::Streaming].contains(&endpoint.state) {
                        current_response_codes
                            .push(ResponseCode::InvalidAseStateMachineTransition { ase_id });
                        continue;
                    }
                    let (sender, recv) = oneshot::channel();
                    waiting.push(recv);
                    events.push(ServiceEvent::UpdateMetadata {
                        peer_id,
                        ase_id,
                        metadata: metadata.clone(),
                        responder: UpdateMetadataResponder {
                            endpoint: endpoint.clone(),
                            metadata,
                            sender,
                        },
                    });
                }
            }
        }
        (
            events,
            AseControlOperationFut {
                peer_id,
                opcode,
                current_response_codes,
                endpoints,
                waiting: waiting.into_iter().collect(),
            },
        )
    }
}

impl<T: bt_gatt::ServerTypes> Stream for AudioStreamControlServiceServer<T> {
    type Item = Result<ServiceEvent, Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Option<Self::Item>> {
        loop {
            self.as_mut().poll_operations(cx);
            let mut this = self.as_mut().project();
            if let Some(event) = this.outgoing_events.pop_front() {
                return Poll::Ready(Some(Ok(event)));
            }
            let gatt_event = match futures::ready!(this.local_service.as_mut().poll_next(cx)) {
                None => return Poll::Ready(None),
                Some(Err(e)) => return Poll::Ready(Some(Err(e))),
                Some(Ok(event)) => event,
            };
            use bt_gatt::server::ServiceEvent::*;
            let peer_id = gatt_event.peer_id();
            let peer_entry = this
                .client_endpoints
                .entry(peer_id)
                .or_insert_with(|| this.default_client_endpoints.clone_for_peer(peer_id));
            match gatt_event {
                Read { handle, offset, responder, .. } => {
                    let offset = offset as usize;
                    if handle == CONTROL_POINT_HANDLE {
                        responder.error(GattError::ReadNotPermitted);
                        continue;
                    }
                    let Some(ase_id) = peer_entry.handles.get(&handle) else {
                        responder.error(GattError::InvalidHandle);
                        continue;
                    };
                    let Some(endpoint) = peer_entry.endpoints.get(ase_id) else {
                        responder.error(GattError::UnlikelyError);
                        continue;
                    };
                    let value = endpoint.into_char_value();
                    if offset > value.len() {
                        responder.error(GattError::InvalidOffset);
                        continue;
                    }
                    responder.respond(&value[offset..]);
                    continue;
                }
                Write { peer_id, handle, offset, value, responder } => {
                    if handle != CONTROL_POINT_HANDLE {
                        responder.error(GattError::WriteNotPermitted);
                        continue;
                    }
                    if offset != 0 {
                        // Offset write isn't allowed by the service?
                        // TODO: determine if partial writes should be allowed
                        responder.error(GattError::InvalidOffset);
                        continue;
                    }
                    responder.acknowledge();
                    match AseControlOperation::try_from(value.to_owned()) {
                        Ok(op) => self.as_mut().queue_operation(peer_id, op),
                        Err(response_code) => {
                            this.local_service.notify(
                                &CONTROL_POINT_HANDLE,
                                &response_code.error_notify_value(),
                                &[peer_id],
                            );
                        }
                    };
                    continue;
                }
                ClientConfiguration { peer_id, handle, notification_type } => {
                    log::info!(
                        "ASCS Got ClientConfig for {peer_id:?}: {handle:?} {notification_type:?}"
                    );
                }
                PeerInfo { peer_id, mtu, connected, .. } => {
                    log::info!(
                        "ASCS got PeerInfo {peer_id:?}: mtu {mtu:?}, connected: {connected:?}"
                    );
                }
                _ => continue,
            }
        }
    }
}

impl<T: bt_gatt::ServerTypes> FusedStream for AudioStreamControlServiceServer<T> {
    fn is_terminated(&self) -> bool {
        self.local_service.is_terminated()
    }
}
