syntax = "proto3";
package zed.messages;

message Envelope {
    uint32 id = 1;
    optional uint32 responding_to = 2;
    optional uint32 original_sender_id = 3;
    oneof payload {
        Ack ack = 4;
        Error error = 5;
        Ping ping = 6;

        RegisterProject register_project = 7;
        RegisterProjectResponse register_project_response = 8;
        UnregisterProject unregister_project = 9;
        ShareProject share_project = 10;
        UnshareProject unshare_project = 11;
        JoinProject join_project = 12;
        JoinProjectResponse join_project_response = 13;
        LeaveProject leave_project = 14;
        AddProjectCollaborator add_project_collaborator = 15;
        RemoveProjectCollaborator remove_project_collaborator = 16;

        RegisterWorktree register_worktree = 17;
        UnregisterWorktree unregister_worktree = 18;
        ShareWorktree share_worktree = 19;
        UpdateWorktree update_worktree = 20;
        UpdateDiagnosticSummary update_diagnostic_summary = 21;
        DiskBasedDiagnosticsUpdating disk_based_diagnostics_updating = 22;
        DiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 23;

        OpenBuffer open_buffer = 24;
        OpenBufferResponse open_buffer_response = 25;
        CloseBuffer close_buffer = 26;
        UpdateBuffer update_buffer = 27;
        SaveBuffer save_buffer = 28;
        BufferSaved buffer_saved = 29;
        FormatBuffer format_buffer = 30;

        GetChannels get_channels = 31;
        GetChannelsResponse get_channels_response = 32;
        JoinChannel join_channel = 33;
        JoinChannelResponse join_channel_response = 34;
        LeaveChannel leave_channel = 35;
        SendChannelMessage send_channel_message = 36;
        SendChannelMessageResponse send_channel_message_response = 37;
        ChannelMessageSent channel_message_sent = 38;
        GetChannelMessages get_channel_messages = 39;
        GetChannelMessagesResponse get_channel_messages_response = 40;

        UpdateContacts update_contacts = 41;

        GetUsers get_users = 42;
        GetUsersResponse get_users_response = 43;
    }
}

// Messages

message Ping {}

message Ack {}

message Error {
    string message = 1;
}

message RegisterProject {}

message RegisterProjectResponse {
    uint64 project_id = 1;
}

message UnregisterProject {
    uint64 project_id = 1;
}

message ShareProject {
    uint64 project_id = 1;
}

message UnshareProject {
    uint64 project_id = 1;
}

message JoinProject {
    uint64 project_id = 1;
}

message JoinProjectResponse {
    uint32 replica_id = 2;
    repeated Worktree worktrees = 3;
    repeated Collaborator collaborators = 4;
}

message LeaveProject {
    uint64 project_id = 1;
}

message RegisterWorktree {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    string root_name = 3;
    repeated string authorized_logins = 4;
}

message UnregisterWorktree {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
}

message ShareWorktree {
    uint64 project_id = 1;
    Worktree worktree = 2;
}

message UpdateWorktree {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    string root_name = 3;
    repeated Entry updated_entries = 4;
    repeated uint64 removed_entries = 5;
}

message AddProjectCollaborator {
    uint64 project_id = 1;
    Collaborator collaborator = 2;
}

message RemoveProjectCollaborator {
    uint64 project_id = 1;
    uint32 peer_id = 2;
}

message OpenBuffer {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    string path = 3;
}

message OpenBufferResponse {
    Buffer buffer = 1;
}

message CloseBuffer {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    uint64 buffer_id = 3;
}

message UpdateBuffer {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    uint64 buffer_id = 3;
    repeated Operation operations = 4;
}

message SaveBuffer {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    uint64 buffer_id = 3;
}

message BufferSaved {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    uint64 buffer_id = 3;
    repeated VectorClockEntry version = 4;
    Timestamp mtime = 5;
}

message FormatBuffer {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    uint64 buffer_id = 3;
}

message UpdateDiagnosticSummary {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
    DiagnosticSummary summary = 3;
}

message DiagnosticSummary {
    string path = 3;
    uint32 error_count = 4;
    uint32 warning_count = 5;
    uint32 info_count = 6;
    uint32 hint_count = 7;
}

message DiskBasedDiagnosticsUpdating {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
}

message DiskBasedDiagnosticsUpdated {
    uint64 project_id = 1;
    uint64 worktree_id = 2;
}

message GetChannels {}

message GetChannelsResponse {
    repeated Channel channels = 1;
}

message JoinChannel {
    uint64 channel_id = 1;
}

message JoinChannelResponse {
    repeated ChannelMessage messages = 1;
    bool done = 2;
}

message LeaveChannel {
    uint64 channel_id = 1;
}

message GetUsers {
    repeated uint64 user_ids = 1;
}

message GetUsersResponse {
    repeated User users = 1;
}

message SendChannelMessage {
    uint64 channel_id = 1;
    string body = 2;
    Nonce nonce = 3;
}

message SendChannelMessageResponse {
    ChannelMessage message = 1;
}

message ChannelMessageSent {
    uint64 channel_id = 1;
    ChannelMessage message = 2;
}

message GetChannelMessages {
    uint64 channel_id = 1;
    uint64 before_message_id = 2;
}

message GetChannelMessagesResponse {
    repeated ChannelMessage messages = 1;
    bool done = 2;
}

message UpdateContacts {
    repeated Contact contacts = 1;
}

// Entities

message Collaborator {
    uint32 peer_id = 1;
    uint32 replica_id = 2;
    uint64 user_id = 3;
}

message User {
    uint64 id = 1;
    string github_login = 2;
    string avatar_url = 3;
}

message Worktree {
    uint64 id = 1;
    string root_name = 2;
    repeated Entry entries = 3;
    repeated DiagnosticSummary diagnostic_summaries = 4;
}

message Entry {
    uint64 id = 1;
    bool is_dir = 2;
    string path = 3;
    uint64 inode = 4;
    Timestamp mtime = 5;
    bool is_symlink = 6;
    bool is_ignored = 7;
}

message Buffer {
    uint64 id = 1;
    string visible_text = 2;
    string deleted_text = 3;
    repeated BufferFragment fragments = 4;
    repeated UndoMapEntry undo_map = 5;
    repeated VectorClockEntry version = 6;
    repeated SelectionSet selections = 7;
    repeated Diagnostic diagnostics = 8;
    uint32 lamport_timestamp = 9;
    repeated Operation deferred_operations = 10;
}

message BufferFragment {
    uint32 replica_id = 1;
    uint32 local_timestamp = 2;
    uint32 lamport_timestamp = 3;
    uint32 insertion_offset = 4;
    uint32 len = 5;
    bool visible =  6;
    repeated VectorClockEntry deletions = 7;
    repeated VectorClockEntry max_undos = 8;
}

message SelectionSet {
    uint32 replica_id = 1;
    repeated Selection selections = 2;
    uint32 lamport_timestamp = 3;
}

message Selection {
    uint64 id = 1;
    Anchor start = 2;
    Anchor end = 3;
    bool reversed = 4;
}

message Anchor {
    uint32 replica_id = 1;
    uint32 local_timestamp = 2;
    uint64 offset = 3;
    Bias bias = 4;
}

enum Bias {
    Left = 0;
    Right = 1;
}

message UpdateDiagnostics {
    uint32 replica_id = 1;
    uint32 lamport_timestamp = 2;
    repeated Diagnostic diagnostics = 3;
}

message Diagnostic {
    Anchor start = 1;
    Anchor end = 2;
    Severity severity = 3;
    string message = 4;
    optional string code = 5;
    uint64 group_id = 6;
    bool is_primary = 7;
    bool is_valid = 8;
    bool is_disk_based = 9;

    enum Severity {
        None = 0;
        Error = 1;
        Warning = 2;
        Information = 3;
        Hint = 4;
    }
}

message Operation {
    oneof variant {
        Edit edit = 1;
        Undo undo = 2;
        UpdateSelections update_selections = 3;
        UpdateDiagnostics update_diagnostics = 4;
    }

    message Edit {
        uint32 replica_id = 1;
        uint32 local_timestamp = 2;
        uint32 lamport_timestamp = 3;
        repeated VectorClockEntry version = 4;
        repeated Range ranges = 5;
        optional string new_text = 6;
    }

    message Undo {
        uint32 replica_id = 1;
        uint32 local_timestamp = 2;
        uint32 lamport_timestamp = 3;
        repeated Range ranges = 4;
        repeated VectorClockEntry version = 5;
        repeated UndoCount counts = 6;
    }

    message UpdateSelections {
        uint32 replica_id = 1;
        uint32 lamport_timestamp = 3;
        repeated Selection selections = 4;
    }
}

message UndoMapEntry {
    uint32 replica_id = 1;
    uint32 local_timestamp = 2;
    repeated UndoCount counts = 3;
}

message UndoCount {
    uint32 replica_id = 1;
    uint32 local_timestamp = 2;
    uint32 count = 3;
}

message VectorClockEntry {
    uint32 replica_id = 1;
    uint32 timestamp = 2;
}

message Timestamp {
    uint64 seconds = 1;
    uint32 nanos = 2;
}

message Range {
    uint64 start = 1;
    uint64 end = 2;
}

message Nonce {
    uint64 upper_half = 1;
    uint64 lower_half = 2;
}

message Channel {
    uint64 id = 1;
    string name = 2;
}

message ChannelMessage {
    uint64 id = 1;
    string body = 2;
    uint64 timestamp = 3;
    uint64 sender_id = 4;
    Nonce nonce = 5;
}

message Contact {
    uint64 user_id = 1;
    repeated ProjectMetadata projects = 2;
}

message ProjectMetadata {
    uint64 id = 1;
    bool is_shared = 2;
    repeated string worktree_root_names = 3;
    repeated uint64 guests = 4;
}
