// 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::{ServiceDefinition, ServiceId};
use bt_gatt::types::{
    AttributePermissions, CharacteristicProperties, CharacteristicProperty, Handle, SecurityLevels,
    ServiceKind,
};
use bt_gatt::Characteristic;

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

/// Specification of a mandatory GATT characteristic for MCS.
struct CharacteristicSpec {
    handle: Handle,
    uuid: Uuid,
    properties: &'static [CharacteristicProperty],
}

/// All the mandatory characteristics defined in MCS v1.0.1 Section 3.
const MANDATORY_CHARACTERISTICS: [CharacteristicSpec; 13] = [
    CharacteristicSpec {
        handle: MEDIA_PLAYER_NAME_HANDLE,
        uuid: MEDIA_PLAYER_NAME_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: TRACK_CHANGED_HANDLE,
        uuid: TRACK_CHANGED_UUID,
        properties: &[CharacteristicProperty::Notify],
    },
    CharacteristicSpec {
        handle: TRACK_TITLE_HANDLE,
        uuid: TRACK_TITLE_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: TRACK_DURATION_HANDLE,
        uuid: TRACK_DURATION_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: TRACK_POSITION_HANDLE,
        uuid: TRACK_POSITION_UUID,
        properties: CharacteristicProperty::READ_WRITE_NOTIFY,
    },
    CharacteristicSpec {
        handle: PLAYBACK_SPEED_HANDLE,
        uuid: PLAYBACK_SPEED_UUID,
        properties: CharacteristicProperty::READ_WRITE_NOTIFY,
    },
    CharacteristicSpec {
        handle: SEEKING_SPEED_HANDLE,
        uuid: SEEKING_SPEED_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: PLAYING_ORDER_HANDLE,
        uuid: PLAYING_ORDER_UUID,
        properties: CharacteristicProperty::READ_WRITE_NOTIFY,
    },
    CharacteristicSpec {
        handle: PLAYING_ORDERS_SUPPORTED_HANDLE,
        uuid: PLAYING_ORDERS_SUPPORTED_UUID,
        properties: &[CharacteristicProperty::Read],
    },
    CharacteristicSpec {
        handle: MEDIA_STATE_HANDLE,
        uuid: MEDIA_STATE_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: MEDIA_CONTROL_POINT_HANDLE,
        uuid: MEDIA_CONTROL_POINT_UUID,
        properties: CharacteristicProperty::WRITE_NOTIFY,
    },
    CharacteristicSpec {
        handle: MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE,
        uuid: MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UUID,
        properties: CharacteristicProperty::READ_NOTIFY,
    },
    CharacteristicSpec {
        handle: CONTENT_CONTROL_ID_HANDLE,
        uuid: CONTENT_CONTROL_ID_UUID,
        properties: &[CharacteristicProperty::Read],
    },
];

/// 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(spec: &CharacteristicSpec) -> Characteristic {
    let properties: CharacteristicProperties = spec.properties.iter().copied().collect();
    Characteristic {
        handle: spec.handle,
        uuid: spec.uuid,
        properties: properties.clone(),
        permissions: AttributePermissions::with_levels(
            &properties,
            &SecurityLevels::encryption_required(),
        ),
        descriptors: Vec::new(),
    }
}

/// 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 spec in &MANDATORY_CHARACTERISTICS {
            service_def.add_characteristic(build_mandatory_characteristic(spec))?;
        }

        Ok(service_def)
    }
}

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

    #[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();

        assert_eq!(characteristics.len(), MANDATORY_CHARACTERISTICS.len());

        for (i, spec) in MANDATORY_CHARACTERISTICS.iter().enumerate() {
            let chrc = characteristics[i];
            assert_eq!(chrc.handle, spec.handle);
            assert_eq!(chrc.uuid, spec.uuid);
            assert_eq!(chrc.properties.0.as_slice(), spec.properties);

            let expected_properties: CharacteristicProperties =
                spec.properties.iter().copied().collect();
            let expected_permissions = AttributePermissions::with_levels(
                &expected_properties,
                &SecurityLevels::encryption_required(),
            );
            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));
    }

    // TODO(b/540400364): Add a test verifying that publishing two McsServer
    // instances with the same CCID to a GATT server fails with an
    // AlreadyPublished error.
}
