// 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};

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<T: crate::GattTypes> {
    /// 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) -> T::FindServicesFut;
}

pub trait PeerServiceHandle<T: crate::GattTypes> {
    fn uuid(&self) -> Uuid;
    fn is_primary(&self) -> bool;
    fn connect(&self) -> T::ServiceConnectFut;
}

/// Implement when a type can be deserialized from a characteristic value.
pub trait FromCharacteristic: Sized {
    const UUID: Uuid;

    /// Create this type from a Characteristic and an initial value.
    fn from_chr(
        characteristic: Characteristic,
        value: &[u8],
    ) -> ::core::result::Result<Self, bt_common::packet_encoding::Error>;

    /// Attempt to update the type when supplied with the `new_value`, which may
    /// or may not be the complete value.
    fn update(
        &mut self,
        new_value: &[u8],
    ) -> ::core::result::Result<&mut Self, bt_common::packet_encoding::Error>;
}

#[derive(Debug, Clone)]
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<T: crate::GattTypes> {
    /// 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>) -> T::CharacteristicDiscoveryFut;

    /// 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],
    ) -> T::ReadFut<'a>;

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

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

    fn write_descriptor<'a>(&self, handle: &Handle, offset: u16, buf: &'a [u8]) -> T::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) -> T::NotificationStream;
}

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

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

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

    pub fn uuid(&self) -> Uuid {
        self.uuid
    }

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

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