// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

syntax = "proto3";

option java_multiple_files = true;

package anki.collection;

import "anki/generic.proto";
import "anki/sync.proto";

service CollectionService {
  rpc CheckDatabase(generic.Empty) returns (CheckDatabaseResponse);
  rpc GetUndoStatus(generic.Empty) returns (UndoStatus);
  rpc Undo(generic.Empty) returns (OpChangesAfterUndo);
  rpc Redo(generic.Empty) returns (OpChangesAfterUndo);
  rpc AddCustomUndoEntry(generic.String) returns (generic.UInt32);
  rpc MergeUndoEntries(generic.UInt32) returns (OpChanges);
  rpc LatestProgress(generic.Empty) returns (Progress);
  rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
}

// Implicitly includes any of the above methods that are not listed in the
// backend service.
service BackendCollectionService {
  rpc OpenCollection(OpenCollectionRequest) returns (generic.Empty);
  rpc CloseCollection(CloseCollectionRequest) returns (generic.Empty);
  // Create a no-media backup. Caller must ensure there is no active
  // transaction. Unlike a collection export, does not require reopening the DB,
  // as there is no downgrade step.
  // Returns false if it's not time to make a backup yet.
  rpc CreateBackup(CreateBackupRequest) returns (generic.Bool);
  // If a backup is running, wait for it to complete. Will return an error
  // if the backup encountered an error.
  rpc AwaitBackupCompletion(generic.Empty) returns (generic.Empty);
  rpc LatestProgress(generic.Empty) returns (Progress);
  rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
}

message OpenCollectionRequest {
  string collection_path = 1;
  string media_folder_path = 2;
  string media_db_path = 3;
}

message CloseCollectionRequest {
  bool downgrade_to_schema11 = 1;
}

message CheckDatabaseResponse {
  repeated string problems = 1;
}

message OpChanges {
  bool card = 1;
  bool note = 2;
  bool deck = 3;
  bool tag = 4;
  bool notetype = 5;
  bool config = 6;
  bool deck_config = 11;
  bool mtime = 12;

  bool browser_table = 7;
  bool browser_sidebar = 8;
  // editor and displayed card in review screen
  bool note_text = 9;
  // whether to call .reset() and getCard()
  bool study_queues = 10;
}

// Allows frontend code to extract changes from other messages like
// ImportResponse without decoding other potentially large fields.
message OpChangesOnly {
  collection.OpChanges changes = 1;
}

message OpChangesWithCount {
  OpChanges changes = 1;
  uint32 count = 2;
}

message OpChangesWithId {
  OpChanges changes = 1;
  int64 id = 2;
}

message UndoStatus {
  string undo = 1;
  string redo = 2;
  uint32 last_step = 3;
}

message OpChangesAfterUndo {
  OpChanges changes = 1;
  string operation = 2;
  int64 reverted_to_timestamp = 3;
  UndoStatus new_status = 4;
  uint32 counter = 5;
}

message Progress {
  message FullSync {
    uint32 transferred = 1;
    uint32 total = 2;
  }

  message NormalSync {
    string stage = 1;
    string added = 2;
    string removed = 3;
  }

  message DatabaseCheck {
    string stage = 1;
    uint32 stage_total = 2;
    uint32 stage_current = 3;
  }

  oneof value {
    generic.Empty none = 1;
    sync.MediaSyncProgress media_sync = 2;
    string media_check = 3;
    FullSync full_sync = 4;
    NormalSync normal_sync = 5;
    DatabaseCheck database_check = 6;
    string importing = 7;
    string exporting = 8;
    ComputeParamsProgress compute_params = 9;
    ComputeRetentionProgress compute_retention = 10;
    ComputeMemoryProgress compute_memory = 11;
  }
}

message ComputeParamsProgress {
  // Current iteration
  uint32 current = 1;
  // Total iterations
  uint32 total = 2;
  uint32 reviews = 3;
  // Only used in 'compute all params' case
  uint32 current_preset = 4;
  // Only used in 'compute all params' case
  uint32 total_presets = 5;
}

message ComputeRetentionProgress {
  uint32 current = 1;
  uint32 total = 2;
}

message ComputeMemoryProgress {
  uint32 current_cards = 1;
  uint32 total_cards = 2;
  string label = 3;
}

message CreateBackupRequest {
  string backup_folder = 1;
  // Create a backup even if the configured interval hasn't elapsed yet.
  bool force = 2;
  bool wait_for_completion = 3;
}
