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

use crate::types::*;

use bt_common::{PeerId, Uuid};
use futures::{Future, Stream};

pub enum ServiceKind {
    Primary,
    Secondary,
}

// A short definition of a service that is either being published or has been discovered on a
// peer.
pub struct PeerServiceDefinition {
    /// Service Handle
    /// When publishing services, unique among all services published with [`Server::publish`].
    pub id: u64,
    /// Whether the service is marked as Primary in the GATT server.
    pub kind: ServiceKind,
    /// The UUID identifying the type of service that this is.
    pub uuid: Uuid,
}

/// GATT Client connected to a particular peer.
/// Holding a struct that implements this should attempt to maintain a LE connection to the peer.
pub trait Client {
    type PeerServiceHandleT: PeerServiceHandle;
    type ServiceResultFut: Future<Output = Result<Vec<Self::PeerServiceHandleT>>> + 'static;

    /// The ID of the peer this is connected to.
    fn peer_id(&self) -> PeerId;

    /// Find services by UUID on the peer.
    /// This may cause as much as a full discovery of all services on the peer if the stack deems it
    /// appropriate.
    /// Service information should be up to date at the time returned.
    fn find_service(&self, uuid: Uuid) -> Self::ServiceResultFut;
}

pub trait PeerServiceHandle {
    type PeerServiceT: PeerService;
    type ConnectFut: Future<Output = Result<Self::PeerServiceT>>;

    fn uuid(&self) -> Uuid;
    fn is_primary(&self) -> bool;
    fn connect(&self) -> Self::ConnectFut;
}

#[derive(Debug)]
pub struct CharacteristicNotification {
    pub handle: Handle,
    pub value: Vec<u8>,
    pub maybe_truncated: bool,
}

/// A connection to a GATT Service on a Peer.
/// All operations are done synchronously.
pub trait PeerService {
    type CharacteristicsFut: Future<Output = Result<Vec<Characteristic>>>;
    type NotificationStream: Stream<Item = Result<CharacteristicNotification>>;
    type ReadFut<'a>: Future<Output = Result<(usize, bool)>> + 'a;
    type WriteFut<'a>: Future<Output = Result<()>> + 'a;

    /// Discover characteristics on this service.
    /// If `uuid` is provided, only the characteristics matching `uuid` will be returned.
    /// This operation may use either the Discovery All Characteristics of a Service or
    /// Discovery Characteristic by UUID procedures, regardless of `uuid`.
    fn discover_characteristics(&self, uuid: Option<Uuid>) -> Self::CharacteristicsFut;

    /// Read a characteristic into a buffer, given the handle within the service.
    /// On success, returns the size read and whether the value may have been truncated.
    /// By default this will try to use a long read if the `buf` is larger than a normal read will
    /// allow (22 bytes) or if the offset is non-zero.
    fn read_characteristic<'a>(
        &self,
        handle: &Handle,
        offset: u16,
        buf: &'a mut [u8],
    ) -> Self::ReadFut<'a>;

    fn write_characteristic<'a>(
        &self,
        handle: &Handle,
        mode: WriteMode,
        offset: u16,
        buf: &'a [u8],
    ) -> Self::WriteFut<'a>;

    fn read_descriptor<'a>(
        &self,
        handle: &Handle,
        offset: u16,
        buf: &'a mut [u8],
    ) -> Self::ReadFut<'a>;

    fn write_descriptor<'a>(
        &self,
        handle: &Handle,
        offset: u16,
        buf: &'a [u8],
    ) -> Self::WriteFut<'a>;

    /// Subscribe to updates on a Characteristic.
    /// Either notifications or indications will be enabled depending on the properties available,
    /// with indications preferred if they are supported.
    /// Fails if the Characteristic doesn't support indications or notifications.
    /// Errors are delivered through an Err item in the stream.
    /// This will often write to the Client Characteristic Configuration descriptor for the
    /// Characteristic subscribed to.
    /// Updates sent from the peer wlil be delivered to the Stream returned.
    fn subscribe(&self, handle: &Handle) -> Self::NotificationStream;
}

/// Convenience class for communicating with characteristics on a remote peer.
pub struct ServiceCharacteristic<'a, PeerServiceT> {
    service: &'a PeerServiceT,
    characteristic: Characteristic,
    uuid: Uuid,
}

impl<'a, PeerServiceT: PeerService> ServiceCharacteristic<'a, PeerServiceT> {
    pub async fn find(
        service: &'a PeerServiceT,
        uuid: Uuid,
    ) -> Result<Vec<ServiceCharacteristic<'a, PeerServiceT>>> {
        let chrs = service.discover_characteristics(Some(uuid)).await?;
        Ok(chrs
            .into_iter()
            .map(|characteristic| Self {
                service,
                characteristic,
                uuid,
            })
            .collect())
    }
}

impl<'a, PeerServiceT> ServiceCharacteristic<'a, PeerServiceT> {
    pub fn uuid(&self) -> Uuid {
        self.uuid
    }

    pub fn handle(&self) -> &Handle {
        &self.characteristic.handle
    }

    pub fn characteristic(&self) -> &Characteristic {
        &self.characteristic
    }
}

impl<'a, PeerServiceT: PeerService> ServiceCharacteristic<'a, PeerServiceT> {
    pub async fn read(&self, buf: &mut [u8]) -> Result<usize> {
        self.service
            .read_characteristic(self.handle(), 0, buf)
            .await
            .map(|(bytes, _)| bytes)
    }
}
