// 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.ledger.cloud;

using fuchsia.mem;

// This file defines a cloud service that can be used by Ledger to power cloud
// sync.

/// Response status for cloud provider operations.
enum Status : int32 {
    OK = 0;
    AUTH_ERROR = 1;
    ARGUMENT_ERROR = 2;
    INTERNAL_ERROR = 3;
    NETWORK_ERROR = 4;
    NOT_FOUND = 5;
    PARSE_ERROR = 6;
    SERVER_ERROR = 7;
    UNKNOWN_ERROR = -1;
};

/// Cloud service that powers cloud sync for a single user. Top-level interface
/// of this file.
///
/// Closing the client connection to CloudProvider shuts down all controllers
/// (DeviceSets, PageClouds) that were produced by it.
[Discoverable]
protocol CloudProvider {
    /// Retrieves the controller for the user device set.
    GetDeviceSet(request<DeviceSet> device_set) -> (Status status);

    /// Retrieves the controller for cloud sync of a particular page.
    GetPageCloud(bytes app_id, bytes page_id, request<PageCloud> page_cloud)
        -> (Status status);
};

/// Cloud registry of devices participating in cloud sync.
///
/// Closing the client connection to DeviceSet disconnects all watchers set on
/// it.
protocol DeviceSet {
    /// Verifies that the device fingerprint in the cloud is still in the list of
    /// devices, ensuring that the cloud was not erased since the last sync.
    CheckFingerprint(bytes fingerprint) -> (Status status);

    /// Adds the device fingerprint to the list of devices in the cloud.
    SetFingerprint(bytes fingerprint) -> (Status status);

    /// Watches the given |fingerprint| in the cloud so that |watcher| is notified
    /// when the fingerprint is erased.
    ///
    /// At most one watcher can be set at any given time. If more than one watcher
    /// is set, only the one set most recently receives notifications.
    ///
    /// The returned status is:
    ///
    ///   - OK, if setting the watcher succeeded,
    ///   - NOT_FOUND, if the fingerprint was not found in the cloud
    ///   - NETWORK_ERROR, if the watcher couldn't be set due to a network error
    ///
    /// If the returned status is not OK, the corresponding error call is also made
    /// on the watcher.
    SetWatcher(bytes fingerprint, DeviceSetWatcher watcher)
        -> (Status status);

    /// Erases the entire registry of devices. This makes all devices detect that
    /// cloud has been erased.
    Erase() -> (Status status);
};

/// Watcher for push notifications from the cloud registry of devices
/// participating in cloud sync.
protocol DeviceSetWatcher {
    /// Called when cloud provider detects that the cloud storage was erased. No
    /// further calls are made on the watcher after this is called.
    OnCloudErased();

    /// Called when an error occured. Most common errors are:
    ///   - NOT_FOUND, if the fingerprint was not found in the cloud when registering the watcher.
    ///   - NETWORK_ERROR if the network connection is lost.
    ///
    /// No further calls are made on the watcher after this is called.
    OnError(Status status);
};

/// Contains a Buffer containing the FIDL serialization of a SerializedCommits.
struct CommitPack {
    fuchsia.mem.Buffer buffer;
};

/// A continuation token for paginated requests.
struct Token {
    bytes opaque_id;
};

/// A commit as seen by the cloud.
struct SerializedCommit {
    // A unique commit id.
    bytes id;
    // Opaque data stored by Ledger.
    bytes data;
};

/// A list of commits for serialization in CommitPack.
struct SerializedCommits {
    vector<SerializedCommit> commits;
};

/// Handler for cloud sync of a single page.
///
/// Implementation of this class manages a *commit log*, which is an append-only
/// list of commits produced by all devices that participate in syncing this
/// page. Position of commits within the log are references using position
/// tokens, allowing the caller to retrieve the commits added to the cloud since
/// the previous read. (plus possibly more - see comments for GetCommits() and
/// SetWatcher().)
///
/// Closing the client connection to PageCloud disconnects all watchers set on
/// it.
protocol PageCloud {
    /// Adds the given commits to the commit log in the cloud.
    ///
    /// The commits are added in one batch, on the receiving side they are
    /// delivered in the same order in a single OnNewCommits() call.
    AddCommits(CommitPack commits) -> (Status status);

    /// Retrieves commits from the cloud.
    ///
    /// All commits newer than |min_position_token| are guaranteed to be returned.
    /// In addition to that, the response may include additional commits older
    /// than or at |min_position_token|. Passing null |min_position_token|
    /// retrieves all commits.
    ///
    /// If the resulting |status| is |OK|, |commits| contains all matching commits
    /// (might be empty) and |position_token| contains the position token of the
    /// most recent of the |commits| (equivalent to |min_position_token| if
    /// |commits| is empty).
    GetCommits(Token? min_position_token)
        -> (Status status, CommitPack? commits, Token? position_token);

    /// Uploads the given object to the cloud under the given id.
    ///
    /// If the object already exists in the cloud this method returns OK.
    AddObject(bytes id, fuchsia.mem.Buffer buffer) -> (Status status);

    /// Retrieves the object of the given id from the cloud.
    ///
    /// If the resulting |status| is |OK|, |buffer| will contain the object
    /// content. If the resulting |status| is not |OK|, |buffer| will be null.
    GetObject(bytes id)
        -> (Status status, fuchsia.mem.Buffer? buffer);

    /// Watches the cloud for push notifications.
    ///
    /// At most one watcher can be set at any given time. If more than one watcher
    /// is set, only the one set most recently receives notifications.
    ///
    /// All commits newer than |min_position_token| added to the cloud before or
    /// after making this call are guaranteed to be delivered to |watcher|. In
    /// addition to that, additional commits older than or at |min_position_token|
    /// may be delivered to. If |min_position_token| is null, notifications for
    /// all commits are delivered.
    SetWatcher(Token? min_position_token, PageCloudWatcher watcher)
        -> (Status status);
};

/// Watcher for push notifications from cloud sync of a single page.
protocol PageCloudWatcher {
    /// Called when new commits are added to the commit log in the cloud.
    ///
    /// The method takes the list of new |commits| along with the |position_token|
    /// of the most recent of them.
    ///
    /// No subsequent calls are made until the client calls the callback of the
    /// previous one.
    OnNewCommits(CommitPack commits, Token position_token) -> ();

    /// Called when a new object is added to the cloud.
    ///
    /// The method takes the |id| and the content of the new object.
    ///
    /// No subsequent calls are made until the client calls the callback of the
    /// previous one.
    OnNewObject(bytes id, fuchsia.mem.Buffer buffer) -> ();

    /// Called when an error occurs.
    ///
    /// No further calls are made on the watcher after this is called. The client
    /// can then re-establish the watcher by calling SetWatcher() again.
    ///
    /// The status is one of:
    ///
    ///   - AUTH_ERROR, if the auth token needs a refresh
    ///   - NETWORK_ERROR, if the connection was dropped
    ///   - PARSE_ERROR, if an invalid server notification was received
    OnError(Status status);
};
