syntax = "proto3";

message Message {
  enum Type {
    SENDER_DELIVERY_RECEIPT = 0;
    PLAINTEXT_CONTENT       = 1;
    CIPHERTEXT              = 2;
    PREKEY_BUNDLE           = 3;
    TEST_NOTIFICATION       = 4;
    CIPHERTEXT_V2           = 5;
  }
  Type                      type              = 1;
  string                    receipt_id        = 2;
  optional bytes            encrypted_content = 3;
  optional PlaintextContent plaintext_content = 4;
}

message PlaintextContent {
  optional DecryptionErrorMessage decryption_error_message = 1;
  optional RetryErrorMessage      retry_control_error      = 2;

  message RetryErrorMessage { }

  message DecryptionErrorMessage {
    enum Type {
      UNKNOWN        = 0;
      PREKEY_UNKNOWN = 1;
    }
    Type type = 1;
  }
}

message EncryptedContent {

  optional string group_id       = 2;
  optional bool   is_direct_chat = 3;

    /// This can be added, so the receiver can check weather he is up to date with the current profile
  optional int64 sender_profile_counter        = 4;
  optional bytes sender_user_discovery_version = 21;
  optional bool ask_for_friend_promotions     = 25;

  optional MessageUpdate         message_update          = 5;
  optional Media                 media                   = 6;
  optional MediaUpdate           media_update            = 7;
  optional ContactUpdate         contact_update          = 8;
  optional ContactRequest        contact_request         = 9;
  optional FlameSync             flame_sync              = 10;
  optional PushKeys              push_keys               = 11;
  optional Reaction              reaction                = 12;
  optional TextMessage           text_message            = 13;
  optional GroupCreate           group_create            = 14;
  optional GroupJoin             group_join              = 15;
  optional GroupUpdate           group_update            = 16;
  optional ResendGroupPublicKey  resend_group_public_key = 17;
  optional ErrorMessages         error_messages          = 18;
  optional AdditionalDataMessage additional_data_message = 19;
  optional TypingIndicator       typing_indicator        = 20;
  optional UserDiscoveryRequest  user_discovery_request  = 22;
  optional UserDiscoveryUpdate   user_discovery_update   = 23;
  optional KeyVerificationProof  key_verification_proof  = 24;
  optional PasswordLessRecovery  passwordless_recovery   = 26;
  optional PasswordLessRecoveryHeartbeat  passwordless_recovery_heartbeat  = 27;

  message ErrorMessages {
    enum Type {
      ERROR_PROCESSING_MESSAGE_CREATED_ACCOUNT_REQUEST_INSTEAD = 0;
      UNKNOWN_MESSAGE_TYPE                                     = 2;
      SESSION_OUT_OF_SYNC                                      = 3;
      GROUP_NOT_FOUND_OR_NOT_A_MEMBER                          = 4;
    }
    Type   type               = 1;
    string related_receipt_id = 2;
  }

  message GroupCreate {
    // key for the state stored on the server
    bytes state_key            = 3;
    bytes group_public_key     = 4;
    optional string group_name = 5;
  }

  message GroupJoin {
        // key for the state stored on the server
    bytes group_public_key = 1;
  }

  message ResendGroupPublicKey {}

  message GroupUpdate {
    string          group_action_type                      = 1; // GroupActionType.name
    optional int64  affected_contact_id                    = 2;
    optional string new_group_name                         = 3;
    optional int64  new_delete_messages_after_milliseconds = 4;
  }

  message TextMessage {
    string          sender_message_id = 1;
    string          text              = 2;
    int64           timestamp         = 3;
    optional string quote_message_id  = 4;
  }

  message AdditionalDataMessage {
    string         sender_message_id       = 1;
    int64          timestamp               = 2;
    string         type                    = 3;
    optional bytes additional_message_data = 4;
  }

  message Reaction {
    string target_message_id = 1;
    string emoji             = 2;
    bool   remove            = 3;
  }

  message MessageUpdate {
    enum Type {
      DELETE    = 0;
      EDIT_TEXT = 1;
      OPENED    = 2;
    }
    Type            type                        = 1;
    optional string sender_message_id           = 2;
    repeated string multiple_target_message_ids = 3;
    optional string text                        = 4;
    int64           timestamp                   = 5;
  }

  message Media {
    enum Type {
      REUPLOAD = 0;
      IMAGE    = 1;
      VIDEO    = 2;
      GIF      = 3;
      AUDIO    = 4;
    }

    string          sender_message_id             = 1;
    Type            type                          = 2;
    optional int64  display_limit_in_milliseconds = 3;
    bool            requires_authentication       = 4;
    int64           timestamp                     = 5;
    optional string quote_message_id              = 6;

    optional bytes download_token   = 7;
    optional bytes encryption_key   = 8;
    optional bytes encryption_mac   = 9;
    optional bytes encryption_nonce = 10;

    optional bytes additional_message_data = 11;
  }

  message MediaUpdate {
    enum Type {
      REOPENED         = 0;
      STORED           = 1;
      DECRYPTION_ERROR = 2;
    }
    Type   type              = 1;
    string target_message_id = 2;
  }

  message ContactRequest {
    enum Type {
      REQUEST = 0;
      REJECT  = 1;
      ACCEPT  = 2;
    }
    Type type = 1;
  }

  message ContactUpdate {
    enum Type {
      REQUEST = 0;
      UPDATE  = 1;
    }

    Type            type                  = 1;
    optional bytes  avatar_svg_compressed = 2;
    optional string username              = 3;
    optional string display_name          = 4;
  }

  message PushKeys {
    enum Type {
      REQUEST = 0;
      UPDATE  = 1;
    }

    Type           type       = 1;
    optional int64 key_id     = 2;
    optional bytes key        = 3;
    optional int64 created_at = 4;
  }

  message FlameSync {
    int64 flame_counter             = 1;
    int64 last_flame_counter_change = 2;
    bool  best_friend               = 3;
    bool  force_update              = 4;
  }

  message TypingIndicator {
    bool  is_typing  = 1;
    int64 created_at = 2;
  }

  message UserDiscoveryRequest  {
    bytes current_version = 1;
  }

  message UserDiscoveryUpdate {
    repeated bytes messages = 1;
  }

  message KeyVerificationProof {
    bytes calculated_mac = 1;
  }

  message PasswordLessRecovery {
    optional bytes recoverySecretShare = 1;
    bool delete = 2;
    int64 threshold = 3;
  }

  message PasswordLessRecoveryHeartbeat {
    bytes hash = 1;
  }

}