// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Use the <code>chrome.syncFileSystem</code> API to save and synchronize data
// on Google Drive. This API is NOT for accessing arbitrary user docs stored in
// Google Drive. It provides app-specific syncable storage for offline and
// caching usage so that the same data can be available across different
// clients. Read <a href="app_storage.html">Manage Data</a> for more on using
// this API.
namespace syncFileSystem {
  enum SyncAction {
    added, updated, deleted
  };

  enum ServiceStatus {
    // The sync service is being initialized (e.g. restoring data from the
    // database, checking connectivity and authenticating to the service etc).
    initializing,

    // The sync service is up and running.
    running,

    // The sync service is not synchronizing files because the remote service
    // needs to be authenticated by the user to proceed.
    authentication_required,

    // The sync service is not synchronizing files because the remote service
    // is (temporarily) unavailable due to some recoverable errors, e.g.
    // network is offline, the remote service is down or not
    // reachable etc. More details should be given by |description| parameter
    // in OnServiceInfoUpdated (which could contain service-specific details).
    temporary_unavailable,

    // The sync service is disabled and the content will never sync.
    // (E.g. this could happen when the user has no account on
    // the remote service or the sync service has had an unrecoverable
    // error.)
    disabled
  };

  enum FileStatus {
    // Not conflicting and has no pending local changes.
    synced,

    // Has one or more pending local changes that haven't been synchronized.
    pending,

    // File conflicts with remote version and must be resolved manually.
    conflicting
  };

  enum SyncDirection {
    local_to_remote, remote_to_local
  };

  enum ConflictResolutionPolicy {
    last_write_win, manual
  };

  dictionary FileInfo {
    // <code>fileEntry</code> for the target file whose status has changed.
    // Contains name and path information of synchronized file.
    // On file deletion,
    // <code>fileEntry</code> information will still be available
    // but file will no longer exist.
    [instanceOf=Entry] object fileEntry;

    // Resulting file status after $ref:onFileStatusChanged event.
    // The status value can be <code>'synced'</code>,
    // <code>'pending'</code> or <code>'conflicting'</code>.
    FileStatus status;

    // Sync action taken to fire $ref:onFileStatusChanged event.
    // The action value can be
    // <code>'added'</code>, <code>'updated'</code> or <code>'deleted'</code>.
    // Only applies if status is <code>'synced'</code>.
    SyncAction? action;

    // Sync direction for the $ref:onFileStatusChanged event.
    // Sync direction value can be
    // <code>'local_to_remote'</code> or <code>'remote_to_local'</code>.
    // Only applies if status is <code>'synced'</code>.
    SyncDirection? direction;
  };

  dictionary FileStatusInfo {
    // One of the Entry's originally given to getFileStatuses.
    [instanceOf=Entry] object fileEntry;

    // The status value can be <code>'synced'</code>,
    // <code>'pending'</code> or <code>'conflicting'</code>.
    FileStatus status;

    // Optional error that is only returned if there was a problem retrieving
    // the FileStatus for the given file.
    DOMString? error;
  };

  dictionary StorageInfo {
    long usageBytes;
    long quotaBytes;
  };

  dictionary ServiceInfo {
    ServiceStatus state;
    DOMString description;
  };

  // A callback type for requestFileSystem.
  callback GetFileSystemCallback =
      void ([instanceOf=DOMFileSystem] object fileSystem);

  // A callback type for getUsageAndQuota.
  callback QuotaAndUsageCallback = void (StorageInfo info);

  // Returns true if operation was successful.
  callback DeleteFileSystemCallback = void (boolean result);

  // A callback type for getFileStatus.
  callback GetFileStatusCallback = void (FileStatus status);

  // A callback type for getFileStatuses.
  callback GetFileStatusesCallback = void (FileStatusInfo[] status);

  // A callback type for getServiceStatus.
  callback GetServiceStatusCallback = void (ServiceStatus status);

  // A callback type for getConflictResolutionPolicy.
  callback GetConflictResolutionPolicyCallback =
      void (ConflictResolutionPolicy policy);

  // A generic result callback to indicate success or failure.
  callback ResultCallback = void ();

  interface Functions {
    // Returns a syncable filesystem backed by Google Drive.
    // The returned <code>DOMFileSystem</code> instance can be operated on
    // in the same way as the Temporary and Persistant file systems (see
    // <a href="http://www.w3.org/TR/file-system-api/">http://www.w3.org/TR/file-system-api/</a>).
    // Calling this multiple times from
    // the same app will return the same handle to the same file system.
    static void requestFileSystem(GetFileSystemCallback callback);

    // Sets the default conflict resolution policy
    // for the <code>'syncable'</code> file storage for the app.
    // By default it is set to <code>'last_write_win'</code>.
    // When conflict resolution policy is set to <code>'last_write_win'</code>
    // conflicts for existing files are automatically resolved next time
    // the file is updated.
    // |callback| can be optionally given to know if the request has
    // succeeded or not.
    static void setConflictResolutionPolicy(
        ConflictResolutionPolicy policy,
        optional ResultCallback callback);

    // Gets the current conflict resolution policy.
    static void getConflictResolutionPolicy(
        GetConflictResolutionPolicyCallback callback);

    // Returns the current usage and quota in bytes
    // for the <code>'syncable'</code> file storage for the app.
    static void getUsageAndQuota([instanceOf=DOMFileSystem] object fileSystem,
                                 QuotaAndUsageCallback callback);

    // Returns the $ref:FileStatus for the given <code>fileEntry</code>.
    // The status value can be <code>'synced'</code>,
    // <code>'pending'</code> or <code>'conflicting'</code>.
    // Note that <code>'conflicting'</code> state only happens when
    // the service's conflict resolution policy is set to <code>'manual'</code>.
    static void getFileStatus([instanceOf=Entry] object fileEntry,
                              GetFileStatusCallback callback);

    // Returns each $ref:FileStatus for the given <code>fileEntry</code> array.
    // Typically called with the result from dirReader.readEntries().
    static void getFileStatuses(object[] fileEntries,
                                GetFileStatusesCallback callback);

    // Returns the current sync backend status.
    static void getServiceStatus(GetServiceStatusCallback callback);
  };

  interface Events {
    // Fired when an error or other status change has happened in the
    // sync backend (for example, when the sync is temporarily disabled due to
    // network or authentication error).
    static void onServiceStatusChanged(ServiceInfo detail);

    // Fired when a file has been updated by the background sync service.
    static void onFileStatusChanged(FileInfo detail);
  };

};
