syntax = "proto3";

package syncspirit.proto;

message Announce {
    bytes           id          = 1;
    repeated string addresses   = 2;
    int64           instance_id = 3;
}

// --- Pre-auth ---

message Hello {
    string device_name    = 1;
    string client_name    = 2;
    string client_version = 3;
}

// --- Header ---

message Header {
    MessageType        type        = 1;
    MessageCompression compression = 2;
}

enum MessageType {
    CLUSTER_CONFIG    = 0;
    INDEX             = 1;
    INDEX_UPDATE      = 2;
    REQUEST           = 3;
    RESPONSE          = 4;
    DOWNLOAD_PROGRESS = 5;
    PING              = 6;
    CLOSE             = 7;
}

enum MessageCompression {
    NONE = 0;
    LZ4  = 1;
}

// --- Actual messages ---

// Cluster Config

message ClusterConfig {
    repeated Folder folders = 1;
}

message Folder {
    string id                   = 1;
    string label                = 2;
    bool   read_only            = 3;
    bool   ignore_permissions   = 4;
    bool   ignore_delete        = 5;
    bool   disable_temp_indexes = 6;
    bool   paused               = 7;

    repeated Device devices = 16;
}

message Device {
    bytes           id                         = 1;
    string          name                       = 2;
    repeated string addresses                  = 3;
    Compression     compression                = 4;
    string          cert_name                  = 5;
    int64           max_sequence               = 6;
    bool            introducer                 = 7;
    uint64          index_id                   = 8;
    bool            skip_introduction_removals = 9;
}

enum Compression {
    METADATA = 0;
    NEVER    = 1;
    ALWAYS   = 2;
}

// Index and Index Update

message Index {
    string            folder = 1;
    repeated FileInfo files  = 2;
}

message IndexUpdate {
    string            folder = 1;
    repeated FileInfo files  = 2;
}

message FileInfo {
    //option (gogoproto.goproto_stringer) = false;
    string             name           = 1;
    FileInfoType       type           = 2;
    int64              size           = 3;
    uint32             permissions    = 4;
    int64              modified_s     = 5;
    int32              modified_ns    = 11;
    uint64             modified_by    = 12;
    bool               deleted        = 6;
    bool               invalid        = 7;
    bool               no_permissions = 8;
    Vector             version        = 9;
    int64              sequence       = 10;
    int32              block_size     = 13;
    repeated BlockInfo Blocks         = 16;
    string             symlink_target = 17;

    // The local_flags fields stores flags that are relevant to the local
    // host only. It is not part of the protocol, doesn't get sent or
    // received (we make sure to zero it), nonetheless we need it on our
    // struct and to be able to serialize it to/from the database.
    uint32 local_flags = 1000;
}

enum FileInfoType {
    FILE              = 0;
    DIRECTORY         = 1;
    SYMLINK_FILE      = 2;
    SYMLINK_DIRECTORY = 3;
    SYMLINK           = 4;
}

message BlockInfo {
    //option (gogoproto.goproto_stringer) = false;
    int64  offset    = 1;
    int32  size      = 2;
    bytes  hash      = 3;
    uint32 weak_hash = 4;
}

message Vector {
    repeated Counter counters = 1;
}

message Counter {
    uint64 id    = 1;
    uint64 value = 2;
}

// Request

message Request {
    int32  id             = 1;
    string folder         = 2;
    string name           = 3;
    int64  offset         = 4;
    int32  size           = 5;
    bytes  hash           = 6;
    bool   from_temporary = 7;
    uint32 weak_hash      = 8;
}

// Response

message Response {
    int32     id   = 1;
    bytes     data = 2;
    ErrorCode code = 3;
}

enum ErrorCode {
    NO_BEP_ERROR = 0;
    GENERIC      = 1;
    NO_SUCH_FILE = 2;
    INVALID_FILE = 3;
}

// DownloadProgress

message DownloadProgress {
    string                              folder  = 1;
    repeated FileDownloadProgressUpdate updates = 2;
}

message FileDownloadProgressUpdate {
    FileDownloadProgressUpdateType update_type   = 1;
    string                         name          = 2;
    Vector                         version       = 3;
    repeated int32                 block_indexes = 4 [packed=false];
}

enum FileDownloadProgressUpdateType {
    APPEND = 0;
    FORGET = 1;
}

// Ping

message Ping {
}

// Close

message Close {
    string reason = 1;
}
