// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package livekit.proto;
option csharp_namespace = "LiveKit.Proto";

import "e2ee.proto";
import "handle.proto";
import "participant.proto";
import "track.proto";
import "video_frame.proto";
import "stats.proto";

// Connect to a new LiveKit room
message ConnectRequest {
  string url = 1;
  string token = 2;
  RoomOptions options = 3;
}
message ConnectResponse {
  uint64 async_id = 1;
}
message ConnectCallback {
  message ParticipantWithTracks {
    OwnedParticipant participant = 1;

    // TrackInfo are not needed here, if we're subscribed to a track, the FfiServer will send
    // a TrackSubscribed event
    repeated OwnedTrackPublication publications = 2;
  }

  uint64 async_id = 1;
  optional string error = 2;
  OwnedRoom room = 3;
  OwnedParticipant local_participant = 4;
  repeated ParticipantWithTracks participants = 5;
}

// Disconnect from the a room
message DisconnectRequest { uint64 room_handle = 1; }
message DisconnectResponse { uint64 async_id = 1; }
message DisconnectCallback { uint64 async_id = 1; }

// Publish a track to the room
message PublishTrackRequest {
  uint64 local_participant_handle = 1;
  uint64 track_handle = 2;
  TrackPublishOptions options = 3;
}
message PublishTrackResponse {
  uint64 async_id = 1;
}
message PublishTrackCallback {
  uint64 async_id = 1;
  optional string error = 2;
  OwnedTrackPublication publication = 3;
}

// Unpublish a track from the room
message UnpublishTrackRequest {
  uint64 local_participant_handle = 1;
  string track_sid = 2;
  bool stop_on_unpublish = 3;
}
message UnpublishTrackResponse {
  uint64 async_id = 1;
}
message UnpublishTrackCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Publish data to other participants
message PublishDataRequest {
  uint64 local_participant_handle = 1;
  uint64 data_ptr = 2;
  uint64 data_len = 3;
  bool reliable = 4;
  repeated string destination_sids = 5 [deprecated=true];
  optional string topic = 6;
  repeated string destination_identities = 7;
}
message PublishDataResponse {
  uint64 async_id = 1;
}
message PublishDataCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Publish transcription messages to room
message PublishTranscriptionRequest {
  uint64 local_participant_handle = 1;
  string participant_identity = 2;
  string track_id = 3;
  repeated TranscriptionSegment segments = 4;
}
message PublishTranscriptionResponse {
  uint64 async_id = 1;
}
message PublishTranscriptionCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Publish Sip DTMF messages to other participants
message PublishSipDtmfRequest {
  uint64 local_participant_handle = 1;
  uint32 code = 2;
  string digit = 3;
  repeated string destination_identities = 4;
}
message PublishSipDtmfResponse {
  uint64 async_id = 1;
}
message PublishSipDtmfCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Change the local participant's metadata
message SetLocalMetadataRequest {
  uint64 local_participant_handle = 1;
  string metadata = 2;
}
message SetLocalMetadataResponse {
  uint64 async_id = 1;
}
message SetLocalMetadataCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Change the local participant's attributes
message SetLocalAttributesRequest {
  uint64 local_participant_handle = 1;
  map<string, string> attributes = 2;
}
message SetLocalAttributesResponse {
  uint64 async_id = 1;
}
message SetLocalAttributesCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Change the local participant's name
message SetLocalNameRequest {
  uint64 local_participant_handle = 1;
  string name = 2;
}
message SetLocalNameResponse {
  uint64 async_id = 1;
}
message SetLocalNameCallback {
  uint64 async_id = 1;
  optional string error = 2;
}

// Change the "desire" to subs2ribe to a track
message SetSubscribedRequest {
  bool subscribe = 1;
  uint64 publication_handle = 2;
}
message SetSubscribedResponse {}

message GetSessionStatsRequest {
  uint64 room_handle = 1;
}
message GetSessionStatsResponse {
  uint64 async_id = 1;
}
message GetSessionStatsCallback {
  uint64 async_id = 1;
  optional string error = 2;
  repeated RtcStats publisher_stats = 3;
  repeated RtcStats subscriber_stats = 4;
}

//
// Options
//

message VideoEncoding {
  uint64 max_bitrate = 1;
  double max_framerate = 2;
}

message AudioEncoding {
  uint64 max_bitrate = 1;
}

message TrackPublishOptions {
  // encodings are optional
  VideoEncoding video_encoding = 1;
  AudioEncoding audio_encoding = 2;
  VideoCodec video_codec = 3;
  bool dtx = 4;
  bool red = 5;
  bool simulcast = 6;
  TrackSource source = 7;
  string stream = 8;
}

enum IceTransportType {
  TRANSPORT_RELAY = 0;
  TRANSPORT_NOHOST = 1;
  TRANSPORT_ALL = 2;
}

enum ContinualGatheringPolicy {
  GATHER_ONCE = 0;
  GATHER_CONTINUALLY = 1;
}

message IceServer {
  repeated string urls = 1;
  string username = 2;
  string password = 3;
}

message RtcConfig {
  optional IceTransportType ice_transport_type = 1;
  optional ContinualGatheringPolicy continual_gathering_policy = 2;
  repeated IceServer ice_servers = 3; // empty fallback to default
}

message RoomOptions {
  bool auto_subscribe = 1;
  bool adaptive_stream = 2;
  bool dynacast = 3;
  optional E2eeOptions e2ee = 4;
  optional RtcConfig rtc_config = 5; // allow to setup a custom RtcConfiguration
  uint32 join_retries = 6;
}

//
// Room
//

enum ConnectionQuality {
  QUALITY_POOR = 0;
  QUALITY_GOOD = 1;
  QUALITY_EXCELLENT = 2;
  QUALITY_LOST = 3;
}

enum ConnectionState {
  CONN_DISCONNECTED = 0;
  CONN_CONNECTED = 1;
  CONN_RECONNECTING = 2;
}

enum DataPacketKind {
  KIND_LOSSY = 0;
  KIND_RELIABLE = 1;
}

enum DisconnectReason {
  UNKNOWN_REASON = 0;
  // the client initiated the disconnect
  CLIENT_INITIATED = 1;
  // another participant with the same identity has joined the room
  DUPLICATE_IDENTITY = 2;
  // the server instance is shutting down
  SERVER_SHUTDOWN = 3;
  // RoomService.RemoveParticipant was called
  PARTICIPANT_REMOVED = 4;
  // RoomService.DeleteRoom was called
  ROOM_DELETED = 5;
  // the client is attempting to resume a session, but server is not aware of it
  STATE_MISMATCH = 6;
  // client was unable to connect fully
  JOIN_FAILURE = 7;
  // Cloud-only, the server requested Participant to migrate the connection elsewhere
  MIGRATION = 8;
  // the signal websocket was closed unexpectedly
  SIGNAL_CLOSE = 9;
  // the room was closed, due to all Standard and Ingress participants having left
  ROOM_CLOSED = 10;
}

message TranscriptionSegment {
  string id = 1;
  string text = 2;
  uint64 start_time = 3;
  uint64 end_time = 4;
  bool final = 5;
  string language = 6;
}

message BufferInfo {
  uint64 data_ptr = 1;
  uint64 data_len = 2;
}

message OwnedBuffer {
  FfiOwnedHandle handle = 1;
  BufferInfo data = 2;
}

message RoomEvent {
  uint64 room_handle = 1;
  oneof message {
    ParticipantConnected participant_connected = 2;
    ParticipantDisconnected participant_disconnected = 3;
    LocalTrackPublished local_track_published = 4;
    LocalTrackUnpublished local_track_unpublished = 5;
    LocalTrackSubscribed local_track_subscribed = 6;
    TrackPublished track_published = 7;
    TrackUnpublished track_unpublished = 8;
    TrackSubscribed track_subscribed = 9;
    TrackUnsubscribed track_unsubscribed = 10;
    TrackSubscriptionFailed track_subscription_failed = 11;
    TrackMuted track_muted = 12;
    TrackUnmuted track_unmuted = 13;
    ActiveSpeakersChanged active_speakers_changed = 14;
    RoomMetadataChanged room_metadata_changed = 15;
    RoomSidChanged room_sid_changed = 16;
    ParticipantMetadataChanged participant_metadata_changed = 17;
    ParticipantNameChanged participant_name_changed = 18;
    ParticipantAttributesChanged participant_attributes_changed = 19;
    ConnectionQualityChanged connection_quality_changed = 20;
    ConnectionStateChanged connection_state_changed = 21;
    // Connected connected = 21;
    Disconnected disconnected = 22;
    Reconnecting reconnecting = 23;
    Reconnected reconnected = 24;
    E2eeStateChanged e2ee_state_changed = 25;
    RoomEOS eos = 26; // The stream of room events has ended
    DataPacketReceived data_packet_received = 27;
    TranscriptionReceived transcription_received = 28;
  }
}

message RoomInfo {
  optional string sid = 1;
  string name = 2;
  string metadata = 3;
}

message OwnedRoom {
  FfiOwnedHandle handle = 1;
  RoomInfo info = 2;
}

message ParticipantConnected { OwnedParticipant info = 1; }

message ParticipantDisconnected { 
  string participant_identity = 1;
}

message LocalTrackPublished {
  // The TrackPublicationInfo comes from the PublishTrack response
  // and the FfiClient musts wait for it before firing this event
  string track_sid = 1;
}

message LocalTrackUnpublished {
  string publication_sid = 1;
}

message LocalTrackSubscribed {
  string track_sid = 2;
}

message TrackPublished {
  string participant_identity = 1;
  OwnedTrackPublication publication = 2;
}

message TrackUnpublished {
  string participant_identity = 1;
  string publication_sid = 2;
}

// Publication isn't needed for subscription events on the FFI
// The FFI will retrieve the publication using the Track sid
message TrackSubscribed {
  string participant_identity = 1;
  OwnedTrack track = 2;
}

message TrackUnsubscribed {
  // The FFI language can dispose/remove the VideoSink here
  string participant_identity = 1;
  string track_sid = 2;
}

message TrackSubscriptionFailed {
  string participant_identity = 1;
  string track_sid = 2;
  string error = 3;
}

message TrackMuted {
  string participant_identity = 1;
  string track_sid = 2;
}

message TrackUnmuted {
  string participant_identity = 1;
  string track_sid = 2;
}

message E2eeStateChanged {
  string participant_identity = 1; // Using sid instead of identity for ffi communication
  EncryptionState state = 2;
}

message ActiveSpeakersChanged { repeated string participant_identities = 1; }

message RoomMetadataChanged { 
  string metadata = 1;
}

message RoomSidChanged {
  string sid = 1;
}

message ParticipantMetadataChanged { 
  string participant_identity = 1;
  string metadata = 2;
}

message ParticipantAttributesChanged {
  string participant_identity = 1;
  map<string, string> attributes = 2;
  map<string, string> changed_attributes = 3;
}

message ParticipantNameChanged { 
  string participant_identity = 1;
  string name = 2;
}

message ConnectionQualityChanged {
  string participant_identity = 1;
  ConnectionQuality quality = 2;
}

message UserPacket {
  OwnedBuffer data = 1;
  optional string topic = 2;
}

message SipDTMF {
  uint32 code = 1;
  optional string digit = 2;
}

message DataPacketReceived {
  DataPacketKind kind = 1;
  string participant_identity = 2; // Can be empty if the data is sent a server SDK
  oneof value {
    UserPacket user = 4;
    SipDTMF sip_dtmf = 5;
  }
}

message TranscriptionReceived {
  optional string participant_identity = 1;
  optional string track_sid = 2;
  repeated TranscriptionSegment segments = 3;
}

message ConnectionStateChanged { ConnectionState state = 1; }

message Connected {}
message Disconnected {
  DisconnectReason reason = 1;
}
message Reconnecting {}
message Reconnected {}

message RoomEOS {}
