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

library fuchsia.bluetooth.gatt;

using fuchsia.bluetooth;

protocol RemoteService {
    /// Returns the characteristics and characteristic descriptors that belong to
    /// this service.
    DiscoverCharacteristics() -> (fuchsia.bluetooth.Status status, vector<Characteristic> characteristics);

    /// Reads the value of the characteristic with `id` and returns it in the
    /// reply. If `status` indicates an error `value` will be empty.
    ///
    /// If the characteristic has a long value (i.e. larger than the current MTU)
    /// this method will return only the first (MTU - 1) bytes of the value. Use
    /// ReadLongCharacteristic() to read larger values or starting at a non-zero
    /// offset.
    ReadCharacteristic(uint64 id) -> (fuchsia.bluetooth.Status status, bytes value);

    /// Reads the complete value of a characteristic with the given `id`. This
    /// procedure should be used if the characteristic is known to have a value
    /// that can not be read in a single request.
    ///
    /// Returns up to `max_bytes` octets of the characteristic value starting at
    /// the given `offset`.
    ///
    /// This may return an error if:
    ///   a. `max_bytes` is 0;
    ///   b. The `offset` is invalid;
    ///   c. The characteristic does not have a long value;
    ///   d. The server does not support the long read procedure.
    ReadLongCharacteristic(uint64 id, uint16 offset, uint16 max_bytes) -> (fuchsia.bluetooth.Status status, bytes:MAX_VALUE_LENGTH value);

    /// Writes `value` to the characteristic with `id`. This operation may return
    /// an error if:
    ///   a. The size of `value` exceeds the current MTU.
    ///   b. The characteristic referred to by `id` does not have the 'write'
    ///      property.
    WriteCharacteristic(uint64 id, bytes value) -> (fuchsia.bluetooth.Status status);

    /// Writes `value` to the characteristic with `id`, beginning at `offset` using
    /// the provided `write_options`.
    ///
    /// This procedure should be used if the value to be written is too long to
    /// fit in a single request or needs to be written at an offset. This may
    /// return an error if:
    ///   a. The `offset` is invalid;
    ///   b. The server does not support the long write procedure.
    ///
    /// Long Writes require multiple messages to the remote service and take longer
    /// to execute than Short Writes. It is not recommended to send a short write
    /// while a long write is in process to the same id and data range. The order
    /// of the responses from this function signify the order in which the remote
    /// service received them, not necessarily the order in which it is called.
    WriteLongCharacteristic(uint64 id, uint16 offset, bytes:MAX_VALUE_LENGTH value, WriteOptions write_options)
        -> (fuchsia.bluetooth.Status status);

    /// Writes `value` to the characteristic with `id` without soliciting an
    /// acknowledgement from the peer. This method has no response and its delivery
    /// cannot be confirmed.
    WriteCharacteristicWithoutResponse(uint64 id, bytes value);

    /// Reads the value of the characteristic descriptor with `id` and returns it
    /// in the reply. If `status` indicates an error, `value` can be ignored.
    ///
    /// If the descriptor has a long value (i.e. larger than the current MTU)
    /// this method will return only the first (MTU - 1) bytes of the value. Use
    /// ReadLongDescriptor() to read larger values or starting at a non-zero
    /// offset.
    ReadDescriptor(uint64 id) -> (fuchsia.bluetooth.Status status, bytes value);

    /// Reads the complete value of a characteristic descriptor with the given `id`.
    /// This procedure should be used if the descriptor is known to have a value
    /// that can not be read in a single request.
    ///
    /// Returns up to `max_bytes` octets of the characteristic value starting at
    /// the given `offset`.
    ///
    /// This may return an error if:
    ///   a. `max_bytes` is 0;
    ///   b. The `offset` is invalid;
    ///   c. The server does not support the long read procedure.
    ReadLongDescriptor(uint64 id, uint16 offset, uint16 max_bytes) -> (fuchsia.bluetooth.Status status, bytes value);

    /// Writes `value` to the characteristic descriptor with `id`. This operation
    /// may return an error if:
    ///   a. The size of `value` exceeds the current MTU.
    ///   b. `id` refers to an internally reserved descriptor type (e.g. the Client
    ///      Characteristic Configuration descriptor).
    WriteDescriptor(uint64 id, bytes value) -> (fuchsia.bluetooth.Status status);

    /// Writes `value` to the characteristic descriptor with `id`, beginning at
    /// `offset`. This procedure should be used if the value to be written is too
    /// long to fit in a single request or needs to be written at an offset. This
    /// may return an error if:
    ///   a. The `offset` is invalid;
    ///   b. The server does not support the long write procedure.
    ///   c. `id` refers to an internally reserved descriptor type (e.g. the Client
    ///      Characteristic Configuration descriptor).
    ///
    /// Long Writes require multiple messages to the remote service and take longer
    /// to execute than Short Writes. It is not recommended to send a short write
    /// while a long write is in process to the same id and data range. The order
    /// of the responses from this function signify the order in which the remote
    /// service received them, not necessarily the order in which it is called.
    WriteLongDescriptor(uint64 id, uint16 offset, bytes:MAX_VALUE_LENGTH value) -> (fuchsia.bluetooth.Status status);

    /// Subscribe or unsubscribe to notifications/indications from the characteristic with
    /// the given `id`. Notifications or indications will be enabled if `enable` is
    /// true or disabled if `enable` is false and they have been enabled for this
    /// client.
    ///
    /// Either notifications or indications will be enabled depending on
    /// characteristic properties. Indications will be preferred if they are
    /// supported.
    ///
    /// This operation fails if the characteristic does not have the "notify" or
    /// "indicate" property or does not contain a Client Characteristic
    /// Configuration descriptor.
    ///
    /// On success, the OnCharacteristicValueUpdated event will be sent whenever
    /// the peer sends a notification or indication. The local host will
    /// automically confirm indications.
    NotifyCharacteristic(uint64 id, bool enable) -> (fuchsia.bluetooth.Status status);

    /// Events:
    /// Called when a characteristic value notification or indication is received.
    -> OnCharacteristicValueUpdated(uint64 id, bytes value);
};

protocol Client {
    /// Enumerates services found on the peer that this Client represents. Results
    /// can be restricted by specifying a list of UUIDs in `uuids`. The returned
    /// ServiceInfo structures will contain only basic information about each
    /// service and the `characteristics` and `includes` fields will be null.
    ///
    /// To further interact with services, clients must obtain a RemoteService
    /// handle by calling ConnectToService().
    ListServices(vector<string>? uuids) -> (fuchsia.bluetooth.Status status, vector<ServiceInfo> services);

    /// Connects the RemoteService with the given identifier.
    ConnectToService(uint64 id, request<RemoteService> service);
};
