syntax = "proto3";
package tailtop.v1;

message Envelope {
  uint32 version = 1;
  string request_id = 2;
  oneof payload {
    Hello hello = 10;
    BeginAuthentication begin_authentication = 11;
    Authenticated authenticated = 12;
    Ping ping = 13;
    Pong pong = 14;
    HostInfo host_info = 15;
    AuthenticationChallenge authentication_challenge = 16;
    PairingRequired pairing_required = 17;
    AuthenticateDevice authenticate_device = 18;
    CompletePairing complete_pairing = 19;
    ListWindows list_windows = 20;
    Windows windows = 21;
    StartWindowStream start_window_stream = 22;
    StopWindowStream stop_window_stream = 23;
    PreviewFrame preview_frame = 24;
    PointerClick pointer_click = 30;
    CursorPosition cursor_position = 31;
    TextInput text_input = 32;
    KeyInput key_input = 33;
    InputAccepted input_accepted = 34;
    PointerEvent pointer_event = 35;
    ListApplications list_applications = 40;
    Applications applications = 41;
    LaunchApplication launch_application = 42;
    Launched launched = 43;
    ListDirectory list_directory = 50;
    DirectoryListing directory_listing = 51;
    FileOperation file_operation = 52;
    FileOperationDone file_operation_done = 53;
    ReadFile read_file = 54;
    FileChunk file_chunk = 55;
    Error error = 90;
  }
}
message Hello { uint32 protocol_version = 1; string client_name = 2; }
message BeginAuthentication { string client_id = 1; string client_name = 2; bytes client_nonce = 3; }
message AuthenticationChallenge { bytes server_nonce = 1; bytes host_proof = 2; }
message PairingRequired { string pairing_id = 1; bytes server_nonce = 2; uint64 expires_at_millis = 3; }
message AuthenticateDevice { string client_id = 1; bytes client_proof = 2; }
message CompletePairing { string pairing_id = 1; string code = 2; bytes client_secret = 3; bytes client_proof = 4; }
message Authenticated { string host_id = 1; bytes host_proof = 2; }
message Ping { uint64 sent_at_micros = 1; }
message Pong { uint64 sent_at_micros = 1; uint64 host_at_micros = 2; }
message HostInfo { string id = 1; string name = 2; string platform = 3; uint32 protocol_version = 4; }
message ListWindows {}
message Rect { double x = 1; double y = 2; double width = 3; double height = 4; }
message Window { uint64 id = 1; string application_id = 2; string application_name = 3; string title = 4; Rect frame = 5; bool visible = 6; }
message Windows { repeated Window windows = 1; }
message StartWindowStream { uint64 window_id = 1; uint32 preferred_width = 2; uint32 preferred_height = 3; uint64 after_sequence = 4; }
message StopWindowStream { uint64 window_id = 1; }
message PreviewFrame { uint64 window_id = 1; uint64 sequence = 2; uint32 width = 3; uint32 height = 4; string mime_type = 5; bytes data = 6; }
enum MouseButton {
  MOUSE_BUTTON_UNSPECIFIED = 0;
  MOUSE_BUTTON_LEFT = 1;
  MOUSE_BUTTON_RIGHT = 2;
}
message PointerClick { uint64 window_id = 1; double x = 2; double y = 3; uint32 click_count = 4; MouseButton button = 5; }
enum PointerPhase {
  POINTER_PHASE_UNSPECIFIED = 0;
  POINTER_PHASE_DOWN = 1;
  POINTER_PHASE_MOVE = 2;
  POINTER_PHASE_UP = 3;
}
message PointerEvent { uint64 window_id = 1; double x = 2; double y = 3; MouseButton button = 4; PointerPhase phase = 5; }
message CursorPosition { uint64 window_id = 1; double x = 2; double y = 3; }
message TextInput { uint64 window_id = 1; string text = 2; repeated Modifier modifiers = 3; }
enum Key {
  KEY_UNSPECIFIED = 0;
  KEY_BACKSPACE = 1;
  KEY_RETURN = 2;
  KEY_TAB = 3;
  KEY_ESCAPE = 4;
  KEY_LEFT = 5;
  KEY_RIGHT = 6;
  KEY_UP = 7;
  KEY_DOWN = 8;
  KEY_DELETE = 9;
}
enum Modifier {
  MODIFIER_UNSPECIFIED = 0;
  MODIFIER_COMMAND = 1;
  MODIFIER_CONTROL = 2;
}
message KeyInput { uint64 window_id = 1; Key key = 2; repeated Modifier modifiers = 3; }
message InputAccepted {}
// include_icons=false returns the list without icon payloads; clients with a
// local icon cache use this to keep refreshes small.
message ListApplications { bool include_icons = 1; }
// icon_png is a small (up to 128px) PNG rendering of the app icon; empty when
// the bundle has no extractable icon.
message Application { string application_id = 1; string name = 2; bytes icon_png = 3; }
message Applications { repeated Application applications = 1; }
message LaunchApplication { string application_id = 1; }
message Launched { string application_id = 1; }
// path "" or "~" resolves to the host user's home directory.
message ListDirectory { string path = 1; }
message DirEntry { string name = 1; bool is_directory = 2; uint64 size = 3; uint64 modified_at_millis = 4; }
message DirectoryListing { string path = 1; repeated DirEntry entries = 2; }
enum FileOp {
  FILE_OP_UNSPECIFIED = 0;
  FILE_OP_RENAME = 1;   // destination = new full path
  FILE_OP_MOVE = 2;     // destination = target directory
  FILE_OP_COPY = 3;     // destination = target directory
  FILE_OP_DELETE = 4;   // moves to Trash
  FILE_OP_MKDIR = 5;    // path = directory to create
  FILE_OP_OPEN = 6;     // open with the default app on the host
}
message FileOperation { FileOp op = 1; string path = 2; string destination = 3; }
message FileOperationDone {}
// Sequential chunked download of a host file. max_length is clamped by the
// host to fit inside one response frame.
message ReadFile { string path = 1; uint64 offset = 2; uint32 max_length = 3; }
message FileChunk { string path = 1; uint64 offset = 2; uint64 total_size = 3; bytes data = 4; bool eof = 5; }
message Error { string code = 1; string message = 2; string permission = 3; }
