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

//! Implements the Media Control Service (MCS) server.

use bt_common::Uuid;
use bt_gatt::server::{LocalService, Server as _, ServiceDefinition, ServiceEvent, ServiceId};
use bt_gatt::types::{
    AttributePermissions, CharacteristicProperties, CharacteristicProperty, Handle, SecurityLevels,
    ServiceKind,
};
use bt_gatt::Characteristic;
use futures::stream::Stream;
use pin_project::pin_project;
use std::future::Future;
use std::task::{Context, Poll, Waker};

use crate::types::*;
use crate::Error;

// ============================================================================
// Mandatory Characteristic Handle Definitions (MCS v1.0.1 Section 3)
// ============================================================================

/// Handle assigned to the Media Player Name characteristic.
const MEDIA_PLAYER_NAME_HANDLE: Handle = Handle(1);
/// Handle assigned to the Track Changed characteristic.
const TRACK_CHANGED_HANDLE: Handle = Handle(2);
/// Handle assigned to the Track Title characteristic.
const TRACK_TITLE_HANDLE: Handle = Handle(3);
/// Handle assigned to the Track Duration characteristic.
const TRACK_DURATION_HANDLE: Handle = Handle(4);
/// Handle assigned to the Track Position characteristic.
const TRACK_POSITION_HANDLE: Handle = Handle(5);
/// Handle assigned to the Playback Speed characteristic.
const PLAYBACK_SPEED_HANDLE: Handle = Handle(6);
/// Handle assigned to the Seeking Speed characteristic.
const SEEKING_SPEED_HANDLE: Handle = Handle(7);
/// Handle assigned to the Playing Order characteristic.
const PLAYING_ORDER_HANDLE: Handle = Handle(8);
/// Handle assigned to the Playing Orders Supported characteristic.
const PLAYING_ORDERS_SUPPORTED_HANDLE: Handle = Handle(9);
/// Handle assigned to the Media State characteristic.
const MEDIA_STATE_HANDLE: Handle = Handle(10);
/// Handle assigned to the Media Control Point characteristic.
const MEDIA_CONTROL_POINT_HANDLE: Handle = Handle(11);
/// Handle assigned to the Media Control Point Opcodes Supported characteristic.
const MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE: Handle = Handle(12);
/// Handle assigned to the Content Control ID (CCID) characteristic.
const CONTENT_CONTROL_ID_HANDLE: Handle = Handle(13);

/// All 13 mandatory characteristics defined in MCS v1.0.1 Section 3.
fn mandatory_characteristics() -> [Characteristic; 13] {
    [
        build_mandatory_characteristic(
            MEDIA_PLAYER_NAME_HANDLE,
            MEDIA_PLAYER_NAME_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_CHANGED_HANDLE,
            TRACK_CHANGED_UUID,
            CharacteristicProperty::Notify,
        ),
        build_mandatory_characteristic(
            TRACK_TITLE_HANDLE,
            TRACK_TITLE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_DURATION_HANDLE,
            TRACK_DURATION_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            TRACK_POSITION_HANDLE,
            TRACK_POSITION_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYBACK_SPEED_HANDLE,
            PLAYBACK_SPEED_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            SEEKING_SPEED_HANDLE,
            SEEKING_SPEED_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYING_ORDER_HANDLE,
            PLAYING_ORDER_UUID,
            CharacteristicProperties::READ_WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            PLAYING_ORDERS_SUPPORTED_HANDLE,
            PLAYING_ORDERS_SUPPORTED_UUID,
            CharacteristicProperty::Read,
        ),
        build_mandatory_characteristic(
            MEDIA_STATE_HANDLE,
            MEDIA_STATE_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            MEDIA_CONTROL_POINT_HANDLE,
            MEDIA_CONTROL_POINT_UUID,
            CharacteristicProperties::WRITE_NOTIFY,
        ),
        build_mandatory_characteristic(
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
            MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UUID,
            CharacteristicProperties::READ_NOTIFY,
        ),
        build_mandatory_characteristic(
            CONTENT_CONTROL_ID_HANDLE,
            CONTENT_CONTROL_ID_UUID,
            CharacteristicProperty::Read,
        ),
    ]
}

/// Specification of a mandatory GATT characteristic for MCS.
/// Constructs a characteristic definition with the specified handle, UUID,
/// properties, and encryption-required permissions conforming to MCS v1.0.1
/// Section 3.
fn build_mandatory_characteristic(
    handle: Handle,
    uuid: Uuid,
    properties: impl Into<CharacteristicProperties>,
) -> Characteristic {
    let properties = properties.into();
    Characteristic {
        handle,
        uuid,
        properties,
        permissions: AttributePermissions::with_levels(
            &properties,
            &SecurityLevels::encryption_required(),
        ),
        descriptors: Vec::new(),
    }
}

/// Internal state for the MCS server.
#[pin_project(project = LocalServiceProj)]
enum LocalServiceState<T: bt_gatt::ServerTypes> {
    /// Service definition has not been registered in the GATT database.
    NotPublished {
        waker: Option<Waker>,
    },
    /// Service registration is in progress.
    Preparing {
        #[pin]
        fut: T::LocalServiceFut,
    },
    /// Service registration is complete and active in the GATT database.
    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 is_published(&self) -> bool {
        matches!(self, LocalServiceState::Published { .. })
    }
}

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

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            match self.as_mut().project() {
                LocalServiceProj::Terminated => return Poll::Ready(None),
                LocalServiceProj::NotPublished { waker } => {
                    *waker = Some(cx.waker().clone());
                    return Poll::Pending;
                }
                LocalServiceProj::Preparing { fut } => match futures::ready!(fut.poll(cx)) {
                    Ok(service) => {
                        let events = service.publish();
                        self.as_mut().set(LocalServiceState::Published { service, events });
                    }
                    Err(e) => {
                        self.as_mut().set(LocalServiceState::NotPublished { waker: None });
                        return Poll::Ready(Some(Err(Error::Gatt(e))));
                    }
                },
                LocalServiceProj::Published { service: _, events } => {
                    match futures::ready!(events.poll_next(cx)) {
                        Some(Ok(event)) => return Poll::Ready(Some(Ok(event))),
                        Some(Err(e)) => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            return Poll::Ready(Some(Err(Error::Gatt(e))));
                        }
                        None => {
                            self.as_mut().set(LocalServiceState::Terminated);
                            return Poll::Ready(None);
                        }
                    }
                }
            }
        }
    }
}

/// Builder for configuring an MCS or GMCS GATT service.
#[derive(Debug, Clone, PartialEq)]
pub struct McsServerBuilder {
    /// Service UUID assigned to the service.
    service_uuid: Uuid,
    /// Content Control ID (CCID) identifying this media service instance. This
    /// is unique across all MCS/GMCS instances on the host server.
    ccid: u8,
    /// Human-readable media player application name.
    player_name: String,
}

impl McsServerBuilder {
    /// Creates a builder for the Generic Media Control Service.
    pub fn generic(ccid: u8, player_name: impl Into<String>) -> Self {
        Self::new(GENERIC_MEDIA_CONTROL_SERVICE_UUID, ccid, player_name)
    }

    /// Creates a builder for an application-specific Media Control Service.
    pub fn instance(ccid: u8, player_name: impl Into<String>) -> Self {
        Self::new(MEDIA_CONTROL_SERVICE_UUID, ccid, player_name)
    }

    fn new(service_uuid: Uuid, ccid: u8, player_name: impl Into<String>) -> Self {
        Self { service_uuid, ccid, player_name: player_name.into() }
    }

    /// Constructs the complete GATT [`ServiceDefinition`] containing all 13
    /// Mandatory Characteristics defined in MCS v1.0.1 Section 3.
    pub fn build_service_definition(&self) -> Result<ServiceDefinition, Error> {
        // The local `ServiceId` is derived from the provided `CCID`. This is valid
        // because the CCID must be unique across all MCS/GMCS instances on the
        // host server. Adding a duplicate characteristic will result in an
        // Error.
        let mut service_def = ServiceDefinition::new(
            ServiceId::new(self.ccid.into()),
            self.service_uuid,
            ServiceKind::Primary,
        );

        for chrc in mandatory_characteristics() {
            service_def.add_characteristic(chrc)?;
        }

        Ok(service_def)
    }

    /// Builds an [`McsServer`] configured with this builder.
    pub fn build<T: bt_gatt::ServerTypes>(self) -> Result<McsServer<T>, Error> {
        let service_def = self.build_service_definition()?;
        Ok(McsServer {
            service_def,
            local_service: Default::default(),
            ccid: self.ccid,
            player_name: self.player_name,
        })
    }
}

/// An instance of a Media Control Service (MCS) or Generic Media Control
/// Service (GMCS) GATT server.
#[pin_project]
pub struct McsServer<T: bt_gatt::ServerTypes> {
    service_def: ServiceDefinition,
    #[pin]
    local_service: LocalServiceState<T>,
    ccid: u8,
    player_name: String,
}

impl<T: bt_gatt::ServerTypes> McsServer<T> {
    /// Returns true if this server is a GMCS server.
    pub fn is_generic_service(&self) -> bool {
        self.service_def.uuid() == GENERIC_MEDIA_CONTROL_SERVICE_UUID
    }

    /// Returns true if the server has successfully published the GATT service.
    pub fn is_published(&self) -> bool {
        self.local_service.is_published()
    }

    /// Publishes the service to the GATT database.
    pub fn publish(&mut self, server: T::Server) -> Result<(), Error> {
        let LocalServiceState::NotPublished { waker } = &mut self.local_service else {
            return Err(Error::AlreadyPublished);
        };

        let waker = waker.take();
        self.local_service =
            LocalServiceState::Preparing { fut: server.prepare(self.service_def.clone()) };

        if let Some(w) = waker {
            w.wake();
        }

        Ok(())
    }
}

impl<T: bt_gatt::ServerTypes> Stream for McsServer<T> {
    type Item = Result<(), Error>;

    fn poll_next(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        loop {
            let mut this = self.as_mut().project();
            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,
            };
            match gatt_event {
                // TODO(b/540400364): Add support for characteristic reads and writes
                _ => continue,
            }
        }
    }
}

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

    use bt_gatt::test_utils::{FakeServer, FakeTypes};
    use futures::{FutureExt, StreamExt};

    #[test]
    fn builder_generic_service_definition() {
        let builder = McsServerBuilder::generic(0x42, "Test Generic Player");
        let service_def = builder
            .build_service_definition()
            .expect("generic service definition builds successfully");
        assert_eq!(service_def.uuid(), GENERIC_MEDIA_CONTROL_SERVICE_UUID);
        assert_eq!(service_def.id(), ServiceId::new(0x42));
        assert_eq!(service_def.kind(), ServiceKind::Primary);
        assert_eq!(service_def.characteristics().count(), 13);
    }

    #[test]
    fn builder_instance_service_definition() {
        let builder = McsServerBuilder::instance(0x07, "Test Instance Player");
        let service_def = builder
            .build_service_definition()
            .expect("instance service definition builds successfully");
        assert_eq!(service_def.uuid(), MEDIA_CONTROL_SERVICE_UUID);
        assert_eq!(service_def.id(), ServiceId::new(0x07));
        assert_eq!(service_def.kind(), ServiceKind::Primary);
        assert_eq!(service_def.characteristics().count(), 13);
    }

    #[test]
    fn mandatory_characteristic_handles_uuids_and_properties() {
        let builder = McsServerBuilder::generic(0x01, "Player");
        let service_def =
            builder.build_service_definition().expect("service definition builds successfully");
        let characteristics: Vec<&Characteristic> = service_def.characteristics().collect();

        let expected_mandatory = mandatory_characteristics();
        assert_eq!(characteristics.len(), expected_mandatory.len());

        for (i, expected) in expected_mandatory.iter().enumerate() {
            let chrc = characteristics[i];
            assert_eq!(chrc.handle, expected.handle);
            assert_eq!(chrc.uuid, expected.uuid);
            assert_eq!(chrc.properties, expected.properties);

            assert_eq!(
                chrc.permissions.read.map(|s| s.encryption),
                expected.permissions.read.map(|s| s.encryption)
            );
            assert_eq!(
                chrc.permissions.write.map(|s| s.encryption),
                expected.permissions.write.map(|s| s.encryption)
            );
            assert_eq!(
                chrc.permissions.update.map(|s| s.encryption),
                expected.permissions.update.map(|s| s.encryption)
            );
        }
    }

    #[test]
    fn service_id_tracks_ccid() {
        let builder1 = McsServerBuilder::instance(0x05, "Player 1");
        let builder2 = McsServerBuilder::instance(0x05, "Player 2");
        let builder3 = McsServerBuilder::instance(0x06, "Player 3");

        let def1 = builder1.build_service_definition().expect("valid definition");
        let def2 = builder2.build_service_definition().expect("valid definition");
        let def3 = builder3.build_service_definition().expect("valid definition");

        assert_eq!(def1.id(), def2.id());
        assert_eq!(def1.id(), ServiceId::new(5));
        assert_ne!(def1.id(), def3.id());
        assert_eq!(def3.id(), ServiceId::new(6));
    }

    #[test]
    fn build_server_success() {
        let generic_server: McsServer<FakeTypes> =
            McsServerBuilder::generic(0x42, "Test Generic Player")
                .build()
                .expect("generic server builds successfully");
        assert!(!generic_server.is_published());
        assert!(generic_server.is_generic_service());

        let instance_server: McsServer<FakeTypes> =
            McsServerBuilder::instance(0x42, "Test Instance Player")
                .build()
                .expect("instance server builds successfully");
        assert!(!instance_server.is_published());
        assert!(!instance_server.is_generic_service());
    }

    #[test]
    fn publish_server_success() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let mut server: McsServer<FakeTypes> =
            McsServerBuilder::generic(0x42, "Test Generic Player")
                .build()
                .expect("server builds successfully");
        assert!(!server.is_published());

        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending before publish");
        };

        server.publish(fake_gatt_server).expect("publish succeeds");

        // Advance state: Preparing -> Published
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending after publish");
        };
        assert!(server.is_published());
    }

    #[test]
    fn publish_server_already_published_error() {
        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let mut server: McsServer<FakeTypes> = McsServerBuilder::generic(0x42, "Test Player")
            .build()
            .expect("server builds successfully");

        server.publish(fake_gatt_server.clone()).expect("initial publish succeeds");
        let err = server.publish(fake_gatt_server);
        assert!(matches!(err, Err(Error::AlreadyPublished)));
    }

    #[test]
    fn duplicate_ccid_publish_error() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, _event_receiver) = FakeServer::new();

        let mut server1: McsServer<FakeTypes> = McsServerBuilder::instance(0x05, "Player 1")
            .build()
            .expect("server1 builds successfully");
        let mut server2: McsServer<FakeTypes> = McsServerBuilder::instance(0x05, "Player 2")
            .build()
            .expect("server2 builds successfully");

        // The first server publishes successfully.
        server1.publish(fake_gatt_server.clone()).expect("server1 publish call succeeds");
        let _ = server1.next().poll_unpin(&mut noop_cx);
        assert!(server1.is_published());

        // The GATT server rejects the second server attempting to publish with the
        // duplicate CCID / ServiceId.
        fake_gatt_server.set_next_prepare_result(Err(bt_gatt::types::Error::AlreadyPublished(
            ServiceId::new(0x05),
        )));
        server2.publish(fake_gatt_server).expect("server2 publish call succeeds");
        let poll_result = server2.next().poll_unpin(&mut noop_cx);
        assert!(matches!(
            poll_result,
            Poll::Ready(Some(Err(Error::Gatt(bt_gatt::types::Error::AlreadyPublished(_)))))
        ));
    }

    #[test]
    fn server_stream_terminates_when_event_stream_closes() {
        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
        let (fake_gatt_server, _event_receiver) = FakeServer::new();
        let mut server: McsServer<FakeTypes> = McsServerBuilder::generic(0x42, "Test Player")
            .build()
            .expect("server builds successfully");

        server.publish(fake_gatt_server).expect("publish succeeds");

        // Advance to Published
        let Poll::Pending = server.next().poll_unpin(&mut noop_cx) else {
            panic!("Should be pending after publish");
        };
        assert!(server.is_published());

        // Replace local_service events stream with a custom channel that can be
        // explicitly closed.
        let (sender, receiver) = futures::channel::mpsc::unbounded();
        let LocalServiceState::Published { service, .. } =
            std::mem::replace(&mut server.local_service, LocalServiceState::Terminated)
        else {
            panic!("Expected server to be in Published state");
        };
        server.local_service = LocalServiceState::Published { service, events: receiver };

        // Dropping the sender closes the event stream.
        drop(sender);

        // Polling the server returns None indicating the stream has terminated.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert!(matches!(poll_result, Poll::Ready(None)));

        // Subsequent polls on terminated state also return None.
        let poll_result = server.next().poll_unpin(&mut noop_cx);
        assert!(matches!(poll_result, Poll::Ready(None)));
    }
}
