syntax = "proto3";

import "fluent.proto";

package backend_proto;

message Empty {}

message OptionalInt32 {
    sint32 val = 1;
}

message BackendInit {
    repeated string preferred_langs = 1;
    string locale_folder_path = 2;
    bool server = 3;
}

message I18nBackendInit {
    repeated string preferred_langs = 4;
    string locale_folder_path = 5;
}

// 1-15 reserved for future use

message BackendInput {
    oneof value {
        TemplateRequirementsIn template_requirements = 16;
        SchedTimingTodayIn sched_timing_today = 17;
        Empty deck_tree = 18;
        SearchCardsIn search_cards = 19;
        SearchNotesIn search_notes = 20;
        RenderCardIn render_card = 21;
        int64 local_minutes_west = 22;
        string strip_av_tags = 23;
        ExtractAVTagsIn extract_av_tags = 24;
        ExtractLatexIn extract_latex = 25;
        AddMediaFileIn add_media_file = 26;
        SyncMediaIn sync_media = 27;
        Empty check_media = 28;
        TrashMediaFilesIn trash_media_files = 29;
        TranslateStringIn translate_string = 30;
        FormatTimeSpanIn format_time_span = 31;
        StudiedTodayIn studied_today = 32;
        CongratsLearnMsgIn congrats_learn_msg = 33;
        Empty empty_trash = 34;
        Empty restore_trash = 35;
        OpenCollectionIn open_collection = 36;
        CloseCollectionIn close_collection = 37;
        int64 get_card = 38;
        Card update_card = 39;
        Card add_card = 40;
        int64 get_deck_config = 41;
        AddOrUpdateDeckConfigIn add_or_update_deck_config = 42;
        Empty all_deck_config = 43;
        Empty new_deck_config = 44;
        int64 remove_deck_config = 45;
        Empty abort_media_sync = 46;
        Empty before_upload = 47;
        RegisterTagsIn register_tags = 48;
        string canonify_tags = 49;
        Empty all_tags = 50;
        int32 get_changed_tags = 51;
        string get_config_json = 52;
        SetConfigJson set_config_json = 53;
        bytes set_all_config = 54;
        Empty get_all_config = 55;
        Empty get_all_notetypes = 56;
        bytes set_all_notetypes = 57;
        Empty get_all_decks = 58;
        bytes set_all_decks = 59;
    }
}

message BackendOutput {
    oneof value {
        // infallible commands
        SchedTimingTodayOut sched_timing_today = 17;
        sint32 local_minutes_west = 22;
        string strip_av_tags = 23;
        ExtractAVTagsOut extract_av_tags = 24;
        ExtractLatexOut extract_latex = 25;
        string translate_string = 30;
        string format_time_span = 31;
        string studied_today = 32;
        string congrats_learn_msg = 33;
        Empty abort_media_sync = 46;

        // fallible commands
        TemplateRequirementsOut template_requirements = 16;
        DeckTreeOut deck_tree = 18;
        SearchCardsOut search_cards = 19;
        SearchNotesOut search_notes = 20;
        RenderCardOut render_card = 21;
        string add_media_file = 26;
        Empty sync_media = 27;
        MediaCheckOut check_media = 28;
        Empty trash_media_files = 29;
        Empty empty_trash = 34;
        Empty restore_trash = 35;
        Empty open_collection = 36;
        Empty close_collection = 37;
        GetCardOut get_card = 38;
        Empty update_card = 39;
        int64 add_card = 40;
        bytes get_deck_config = 41;
        int64 add_or_update_deck_config = 42;
        bytes all_deck_config = 43;
        bytes new_deck_config = 44;
        Empty remove_deck_config = 45;
        Empty before_upload = 47;
        bool register_tags = 48;
        CanonifyTagsOut canonify_tags = 49;
        AllTagsOut all_tags = 50;
        GetChangedTagsOut get_changed_tags = 51;
        bytes get_config_json = 52;
        Empty set_config_json = 53;
        Empty set_all_config = 54;
        bytes get_all_config = 55;
        bytes get_all_notetypes = 56;
        Empty set_all_notetypes = 57;
        bytes get_all_decks = 58;
        Empty set_all_decks = 59;

        BackendError error = 2047;
    }
}

message BackendError {
    // localized error description suitable for displaying to the user
    string localized = 1;
    // error specifics
    oneof value {
        Empty invalid_input = 2;
        Empty template_parse = 3;
        Empty io_error = 4;
        Empty db_error = 5;
        NetworkError network_error = 6;
        SyncError sync_error = 7;
        // user interrupted operation
        Empty interrupted = 8;
        string json_error = 9;
    }
}

message Progress {
    oneof value {
        MediaSyncProgress media_sync = 1;
        string media_check = 2;
    }
}

message NetworkError {
    enum NetworkErrorKind {
        OTHER = 0;
        OFFLINE = 1;
        TIMEOUT = 2;
        PROXY_AUTH = 3;
    }
    NetworkErrorKind kind = 1;
}

message SyncError {
    enum SyncErrorKind {
        OTHER = 0;
        CONFLICT = 1;
        SERVER_ERROR = 2;
        CLIENT_TOO_OLD = 3;
        AUTH_FAILED = 4;
        SERVER_MESSAGE = 5;
        MEDIA_CHECK_REQUIRED = 6;
        RESYNC_REQUIRED = 7;
    }
    SyncErrorKind kind = 1;
}

message MediaSyncProgress {
    string checked = 1;
    string added = 2;
    string removed = 3;
}

message MediaSyncUploadProgress {
    uint32 files = 1;
    uint32 deletions = 2;
}

message TemplateRequirementsIn {
    repeated string template_front = 1;
    map<string, uint32> field_names_to_ordinals = 2;
}

message TemplateRequirementsOut {
    repeated TemplateRequirement requirements = 1;
}

message TemplateRequirement {
    oneof value {
        TemplateRequirementAll all = 1;
        TemplateRequirementAny any = 2;
        Empty none = 3;
    }
}

message TemplateRequirementAll {
    repeated uint32 ords = 1;
}

message TemplateRequirementAny {
    repeated uint32 ords = 1;
}

message SchedTimingTodayIn {
    int64 created_secs = 1;
    int64 now_secs = 2;
    OptionalInt32 created_mins_west = 3;
    OptionalInt32 now_mins_west = 4;
    OptionalInt32 rollover_hour = 5;
}

message SchedTimingTodayOut {
    uint32 days_elapsed = 1;
    int64 next_day_at = 2;
}

message DeckTreeOut {
    DeckTreeNode top = 1;
}

message DeckTreeNode {
    // the components of a deck, split on ::
    repeated string names = 1;
    int64 deck_id = 2;
    uint32 review_count = 3;
    uint32 learn_count = 4;
    uint32 new_count = 5;
    repeated DeckTreeNode children = 6;
    bool collapsed = 7;
}

message RenderCardIn {
    string question_template = 1;
    string answer_template = 2;
    map<string,string> fields = 3;
    int32 card_ordinal = 4;
}

message RenderCardOut {
    repeated RenderedTemplateNode question_nodes = 1;
    repeated RenderedTemplateNode answer_nodes = 2;
}

message RenderedTemplateNode {
    oneof value {
        string text = 1;
        RenderedTemplateReplacement replacement = 2;
    }
}

message RenderedTemplateReplacement {
    string field_name = 1;
    string current_text = 2;
    repeated string filters = 3;
}

message ExtractAVTagsIn {
    string text = 1;
    bool question_side = 2;
}

message ExtractAVTagsOut {
    string text = 1;
    repeated AVTag av_tags = 2;
}

message AVTag {
    oneof value {
        string sound_or_video = 1;
        TTSTag tts = 2;
    }
}

message TTSTag {
    string field_text = 1;
    string lang = 2;
    repeated string voices = 3;
    float speed = 4;
    repeated string other_args = 5;
}

message ExtractLatexIn {
    string text = 1;
    bool svg = 2;
    bool expand_clozes = 3;
}

message ExtractLatexOut {
    string text = 1;
    repeated ExtractedLatex latex = 2;
}

message ExtractedLatex {
    string filename = 1;
    string latex_body = 2;
}

message AddMediaFileIn {
    string desired_name = 1;
    bytes data = 2;
}

message SyncMediaIn {
    string hkey = 1;
    string endpoint = 2;
}

message MediaCheckOut {
    repeated string unused = 1;
    repeated string missing = 2;
    string report = 3;
    bool have_trash = 4;
}

message TrashMediaFilesIn {
    repeated string fnames = 1;
}

message TranslateStringIn {
    FluentString key = 2;
    map<string,TranslateArgValue> args = 3;
}

message TranslateArgValue {
    oneof value {
        string str = 1;
        double number = 2;
    }
}

message FormatTimeSpanIn {
    enum Context {
        PRECISE = 0;
        ANSWER_BUTTONS = 1;
        INTERVALS = 2;
    }

    float seconds = 1;
    Context context = 2;
}

message StudiedTodayIn {
    uint32 cards = 1;
    double seconds = 2;
}

message CongratsLearnMsgIn {
    float next_due = 1;
    uint32 remaining = 2;
}

message OpenCollectionIn {
    string collection_path = 1;
    string media_folder_path = 2;
    string media_db_path = 3;
    string log_path = 4;
}

message SearchCardsIn {
    string search = 1;
    SortOrder order = 2;
}

message SearchCardsOut {
    repeated int64 card_ids = 1;

}

message SortOrder {
    oneof value {
        Empty from_config = 1;
        Empty none = 2;
        string custom = 3;
        BuiltinSearchOrder builtin = 4;
    }
}

message SearchNotesIn {
    string search = 1;
}

message SearchNotesOut {
    repeated int64 note_ids = 2;
}

message BuiltinSearchOrder {
    enum BuiltinSortKind {
        NOTE_CREATION = 0;
        NOTE_MOD = 1;
        NOTE_FIELD = 2;
        NOTE_TAGS = 3;
        NOTE_TYPE = 4;
        CARD_MOD = 5;
        CARD_REPS = 6;
        CARD_DUE = 7;
        CARD_EASE = 8;
        CARD_LAPSES = 9;
        CARD_INTERVAL = 10;
        CARD_DECK = 11;
        CARD_TEMPLATE = 12;
    }
    BuiltinSortKind kind = 1;
    bool reverse = 2;
}


message GetCardOut {
    Card card = 1;
}

message Card {
    int64 id = 1;
    int64 nid = 2;
    int64 did = 3;
    uint32 ord = 4;
    int64 mtime = 5;
    sint32 usn = 6;
    uint32 ctype = 7;
    sint32 queue = 8;
    sint32 due = 9;
    uint32 ivl = 10;
    uint32 factor = 11;
    uint32 reps = 12;
    uint32 lapses = 13;
    uint32 left = 14;
    sint32 odue = 15;
    int64 odid = 16;
    uint32 flags = 17;
    string data = 18;
}

message CloseCollectionIn {
    bool downgrade_to_schema11 = 1;
}

message AddOrUpdateDeckConfigIn {
    bytes config = 1;
    bool preserve_usn_and_mtime = 2;
}

message RegisterTagsIn {
    string tags = 1;
    bool preserve_usn = 2;
    int32 usn = 3;
    bool clear_first = 4;
}

message AllTagsOut {
    repeated TagUsnTuple tags = 1;
}

message TagUsnTuple {
    string tag = 1;
    sint32 usn = 2;
}

message GetChangedTagsOut {
    repeated string tags = 1;
}

message CanonifyTagsOut {
    string tags = 1;
    bool tag_list_changed = 2;
}

message SetConfigJson {
    string key = 1;
    oneof op {
        bytes val = 2;
        Empty remove = 3;
    }
}
