// Copyright 2018 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.avrcp;

using fuchsia.bluetooth as bt;
using zx;

[Discoverable]
protocol PeerManager {
    /// Returns a controller client to a remote target (TG) service at the peer specified by
    /// `peer_id`.
    /// TODO (fxbug.dev/898): change peer_id to fuchsia.bluetooth.PeerId type after BrEdr profile service
    /// switches.
    GetControllerForTarget(bt.PeerIdString peer_id, request<Controller> client) -> () error zx.status;

    /// Set the absolute volume handler.  Only one handler may be set  at at time.
    /// If a second handler is registered it will be dropped and an error will
    /// be returned.
    SetAbsoluteVolumeHandler(AbsoluteVolumeHandler handler) -> () error zx.status;

    /// Sets an implementation of target handler that will vend delegates for each incoming
    /// remote TG -> local CT connections to handle the commands being sent by the remote TG.
    RegisterTargetHandler(TargetHandler handler) -> () error zx.status;
};

/// Handler for absolute volume requests from a remote peer. See AVRCP v 1.6.2 section 6.13.2.
/// Absolute volume is represented as a percentage using one byte with the most significant bit
/// reserved. 0% is represented as 0x0 and 100% as 0x7f. Volume should scaled between the
/// two values.
protocol AbsoluteVolumeHandler {
    /// Requests that the absolute volume of the player be changed.
    /// `requested_volume` is the requested volume by the peer.
    /// Returns the actual volume set locally by the handler.
    SetVolume(uint8 requested_volume) -> (uint8 set_volume);

    /// Returns latest volume of the handler to the AVRCP service. This function should return
    /// immediately on the first call and if the volume has changed since the last call to this
    /// function, otherwise it should only return when the volume has been changed.
    /// Multiple outstanding `OnVolumeChanged` requests can be made - all outstanding calls will
    /// return when the volume has been changed.
    // TODO(fxbug.dev/54002): Update docs when addressed.
    OnVolumeChanged() -> (uint8 new_volume);

    /// Returns the current volume immediately.
    GetCurrentVolume() -> (uint8 volume);
};

/// Client wrapper for local controller (CT) -> remote target (TG) AVCTP connections between devices.
/// A client is high level construct and does not represent a connection with a device.
/// Connections are internally managed and may be shared by multiple clients.
/// The actual connection may be opened on-demand after any command here is called.
protocol Controller {
    /// Returns currently set player application setting values for the `attribute_ids`.
    /// If no `attribute_ids` are provided, this method will query the TG for all valid
    /// attribute ID's, and return the currently set player application setting values.
    GetPlayerApplicationSettings(vector<PlayerApplicationSettingAttributeId>:MAX_ATTRIBUTES attribute_ids)
        -> (PlayerApplicationSettings current_settings) error ControllerError;

    /// Sets the player application settings specified by `requested_settings`. Only
    /// settings specified in the input `requested_settings` will be overwritten.
    /// Returns the actual settings that were set.
    /// Settings provided in the `requested_settings` that are unsupported or unknown
    /// will not be set; the returned `set_settings` will include only the settings
    /// that were successfully set on the remote target.
    SetPlayerApplicationSettings(PlayerApplicationSettings requested_settings)
        -> (PlayerApplicationSettings set_settings) error ControllerError;

    /// Returns the currently playing media attributes.
    /// May send either the GetElementAttributes or GetItemAttributes command depending on what
    /// is supported.
    GetMediaAttributes() -> (MediaAttributes attributes) error ControllerError;

    /// Returns the status of the currently playing media.
    GetPlayStatus() -> (PlayStatus play_status) error ControllerError;

    /// Request the absolute volume on the peer be changed. Returns the actual volume set by the
    /// peer. Values can range from 0x00 to 0x7F (with 100% volume being 0x7F). You may not get a
    /// volume changed notification event from the remote peer as result of changing this.
    SetAbsoluteVolume(uint8 requested_volume) -> (uint8 set_volume) error ControllerError;

    /// Inform target of the controller's battery level.
    InformBatteryStatus(BatteryStatus battery_status) -> () error ControllerError;

    /// Filters notifications that will be received with [`OnNotification`]. Not all notifications
    /// are supported by all peers. Resetting the notification filter may trigger all requested
    /// notification types to post their current value to [`OnNotification`] immediately.
    ///
    /// The `position_change_interval` argument is used to set the interval in seconds that the
    /// controller client would like to be notified of `TRACK_POS_CHANGED` events.
    /// `position_change_interval` is ignored if `TRACK_POS` is not set. The position change interval
    /// is best effort and not a guarantee and events may arrive more frequently or less frequently
    /// than requested.
    SetNotificationFilter(Notifications notifications, uint32 position_change_interval);

    /// Incoming notification events from the target peer. `timestamp` is monotonic wall time
    /// of when the event was received by the peer.
    /// You must call [`NotifyNotificationHandled`] after receving a notification event to
    /// acknowledge delivery. Multiple non-discrete events may be combined into a single
    /// notification if acknowledged after a new event arrives from a peer.
    /// Call [`SetNotificationFilter`] to set the notifications that are requested of the peer.
    /// All notifications are discrete state changes except volume change and position change
    /// notifications.
    -> OnNotification(zx.time timestamp, Notification notification);

    /// Call to acknowledge handling of a notification from [`OnNotification`].
    NotifyNotificationHandled();

    /// Changes the addressed `player_id` on the target when multiple are supported.
    SetAddressedPlayer(uint16 player_id) -> () error ControllerError;

    /// Send an AV\C passthrough key command. Sends both a key down and key up event.
    SendCommand(AvcPanelCommand command) -> () error ControllerError;
};
