export class Meeting {
  /**
   * This represents the unique ID of the meeting that the participant has joined.
   */
  id: string;

  /**
   * This indicates the participant ID of the user who is currently speaking. If no participant is actively speaking, the value is `null`.
   */
  activeSpeakerId: string;

  /**
   * This indicates the participant ID of the user who is currently sharing their screen in the meeting. If no one is presenting, the value is `null`.
   */
  activePresenterId: string;

  /**
   * This represents the participant ID of the main participant in the meeting.
   */
  mainParticipantId: string;

  /**
   * This represents the local participant (you) who joined the meeting.
   */
  localParticipant: Participant;

  /**
   * This represents a map of all remote participants currently in the meeting.
   *
   * - The key represents the participant ID.
   * - The value represents the corresponding `Participant` instance.
   *
   * This map does not include the local participant.
   */
  participants: Map<string, Participant>;

  /**
   * This represents the current state of the livestream.
   */
  livestreamState:
    | "LIVESTREAM_STOPPED"
    | "LIVESTREAM_STARTING"
    | "LIVESTREAM_STARTED"
    | "LIVESTREAM_STOPPING";

  /**
   * This represents the current state of the meeting recording.
   */
  recordingState:
    | "RECORDING_STOPPED"
    | "RECORDING_STARTING"
    | "RECORDING_STARTED"
    | "RECORDING_STOPPING";

  /**
   * This represents the current state of the HLS stream.
   */
  hlsState: "HLS_STOPPED" | "HLS_STARTING" | "HLS_STARTED" | "HLS_STOPPING";

  /**
   * This represents the URLs associated with the ongoing HLS stream.
   *
   * - **playbackHlsUrl** – URL used for playback.
   * - **livestreamUrl** – URL used for live streaming.
   * - ~~**downstreamUrl**~~ – **Deprecated**. Use `playbackHlsUrl` or `livestreamUrl` instead.
   *
   * > **Note**
   * >
   * > `downstreamUrl` is deprecated and should no longer be used.
   */
  hlsUrls: {
    downstreamUrl?: string;
    playbackHlsUrl?: string;
    livestreamUrl?: string;
  };

  /**
   * This represents the current state of real-time transcription.
   */
  transcriptionState:
    | "TRANSCRIPTION_STARTING"
    | "TRANSCRIPTION_STARTED"
    | "TRANSCRIPTION_STOPPING"
    | "TRANSCRIPTION_STOPPED";

  /**
   * This represents whether End-to-End Encryption (E2EE) is enabled for the meeting.
   */
  isE2EEEnabled: boolean;

  /**
   * This represents a map of all participants currently pinned in the meeting.
   *
   * - The key represents the participant ID.
   * - The value represents the pin state, indicating whether the participant’s camera (`cam`) and/or screen share (`share`) is pinned.
   */
  pinnedParticipants: Map<
    string,
    {
      cam: boolean;
      share: boolean;
    }
  >;

  /**
   * This represents the currently selected camera device used during the meeting,returned as a {@link CameraDeviceInfo} object containing details about the active camera.
   */
  selectedCameraDevice: CameraDeviceInfo;

  /**
   * This represents the currently selected microphone device used during the meeting,returned as a {@link MicrophoneDeviceInfo} object containing details about the active microphone.
   */
  selectedMicrophoneDevice: MicrophoneDeviceInfo;

  /**
   * It allows access to the {@link pubSub} functionality.
   */
  pubSub: pubSub;

  /**
   * It allows access to the {@link realtimeStore} functionality.
   */
  realtimeStore: realtimeStore;

  /**
   * - This method can be used to join the meeting.
   * - After initializing a meeting using `initMeeting()`, calling `join()` is required to enter the meeting.
   *
   * **Events associated with `join()`:**
   *
   * - The local participant receives a {@link MeetingEvent.meeting-joined | meeting-joined} event once the meeting is successfully joined.
   * - Remote participants receive a {@link MeetingEvent.participant-joined | participant-joined} event containing the newly joined participant.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.join();
   * ```
   */
  join(): void;

  /**
   * - This method can be used to leave the currently joined meeting.
   *
   * **Events associated with `leave()`:**
   *
   * - The local participant receives a {@link MeetingEvent.meeting-left | meeting-left} event.
   * - All remote participants receive a {@link MeetingEvent.participant-left | participant-left} event containing the participant ID of the user who left.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.leave();
   * ```
   */
  leave(): void;

  /**
   * - This method can be used to change the local participant's mode.
   * - You can switch between the following modes: {@link modes}.
   *
   * > **Info**
   * >
   * > Important changes introduced in JavaScript SDK v0.1.4:
   * > - `CONFERENCE` has been replaced with `SEND_AND_RECV`
   * > - `VIEWER` has been replaced with `SIGNALLING_ONLY`
   *
   * **Events associated with `changeMode()`:**
   *
   * - The participant receives a {@link MeetingEvent.participant-mode-changed | participant-mode-changed} event when the mode is successfully updated.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.changeMode(VideoSDK.Constants.modes.SEND_AND_RECV);
   * ```
   */
  changeMode(mode: "SEND_AND_RECV" | "SIGNALLING_ONLY" | "RECV_ONLY"): void;

  /**
   * - This method can be used to end the current meeting session for all participants.
   * - Calling `end()` removes all participants, including the local participant, and permanently terminates the meeting.
   *
   * **Events associated with `end()`:**
   *
   * - All participants receive the {@link MeetingEvent.meeting-left | meeting-left} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.end();
   * ```
   */
  end(): void;

  /**
   * - This method can be used to disable the local participant’s microphone.
   *
   * **Events associated with `muteMic()`:**
   *
   * - A {@link ParticipantEvent.stream-disabled | stream-disabled} event is emitted with the corresponding {@link Stream} object.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.muteMic();
   * ```
   */
  muteMic(): void;

  /**
   * - This method can be used to enable the local participant’s microphone.
   *
   * **Events associated with `unmuteMic()`:**
   *
   * - A {@link ParticipantEvent.stream-enabled | stream-enabled} event is emitted with the corresponding {@link Stream} object.
   *
   * @param customAudioTrack
   * An optional custom audio track to be used instead of the default one.
   *
   * To learn more, checkout this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track)
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.unmuteMic();
   * ```
   */
  unmuteMic(customAudioTrack?: MediaStream): void;

  /**
   * - This method can be used to disable the local participant’s webcam.
   *
   * **Events associated with `disableWebcam()`:**
   *
   * - A {@link ParticipantEvent.stream-disabled | stream-disabled} event is emitted with the corresponding {@link Stream} object.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.disableWebcam();
   * ```
   */
  disableWebcam(): void;

  /**
   * - This method can be used to enable the local participant’s webcam.
   *
   * **Events associated with `enableWebcam()`:**
   *
   * - A {@link ParticipantEvent.stream-enabled | stream-enabled} event is emitted with the corresponding {@link Stream} object.
   *
   * @param customVideoTrack
   * An optional custom video track to be used instead of the default one.
   *
   * To learn more, checkout this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track)
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.enableWebcam();
   * ```
   */
  enableWebcam(customVideoTrack?: MediaStream): void;

  /**
   * - This method can be used to disable screen sharing for the local participant.
   *
   * **Events associated with `disableScreenShare()`:**
   *
   * - A {@link ParticipantEvent.stream-disabled | stream-disabled} event is emitted with the corresponding {@link Stream} object.
   * - A {@link MeetingEvent.presenter-changed | presenter-changed} event is emitted with `null` as the presenter.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.disableScreenShare();
   * ```
   */
  disableScreenShare(): void;

  /**
   * - This method can be used to enable screen sharing for the local participant.
   *
   * **Events associated with `enableScreenShare()`:**
   *
   * - A {@link ParticipantEvent.stream-enabled | stream-enabled} event is emitted with the corresponding {@link Stream} object.
   * - A {@link MeetingEvent.presenter-changed | presenter-changed} event is emitted with the `presenterId`.
   *
   * @param customScreenSharingTrack An optional custom screen share track to be used instead of the default one.
   *
   * To learn more checkout this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track#custom-screen-share-track)
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.enableScreenShare();
   * ```
   */
  enableScreenShare(customScreenSharingTrack?: MediaStream): void;

  /**
   * - This method can be used to send a message to all participants in the meeting using the data channel.
   *
   * @param payload
   * The data to be sent.
   *
   * - Supported types: `string`, `Blob`, `ArrayBuffer`, `ArrayBufferView`
   * - Maximum allowed size: **15 KiB**
   *
   * @param options
   * @param options.reliability
   * Determines how the message is delivered:
   *
   * - {@link reliabilityMode.RELIABLE} — Guarantees delivery and preserves order (may introduce latency).
   * - {@link reliabilityMode.UNRELIABLE} — Faster delivery but messages may be dropped under poor network conditions.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.send("Hello everyone!", {
   *   reliability: VideoSDK.Constants.reliabilityMode.UNRELIABLE,
   * });
   * ```
   * @returns
   */
  send(
    payload: string | Blob | ArrayBuffer | ArrayBufferView,
    options?: {
      reliability?: "RELIABLE" | "UNRELIABLE";
    }
  ): Promise<boolean>;

  /**
   * - This method can be used to start real-time transcription for the meeting.
   *
   * - All participants, including the local participant, will receive the {@link transcriptionEvents.TRANSCRIPTION_STARTING | TRANSCRIPTION_STARTING} state in the {@link MeetingEvent.transcription-state-changed | transcription-state-changed} event.
   *
   * @param options
   * @param options.webhookUrl
   * A webhook URL that will be called whenever the transcription state changes.
   *
   * @param options.modelConfig
   * Optional model configuration used during transcription.
   *
   * @param options.summary
   * Configuration for real-time transcription summary generation.
   *
   * @param options.summary.enabled
   * Enables or disables summary generation.
   *
   * @param options.summary.prompt
   * Custom instructions used to guide summary generation.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const config = {
   *   webhookUrl: "https://webhook.your-api-server.com",
   *   summary: {
   *     enabled: true,
   *     prompt: "Write summary in sections like Title, Agenda, Speakers, Action Items, and Notes",
   *   },
   * };
   *
   * meeting?.startTranscription(config);
   * ```
   * @returns
   */
  startTranscription(options?: {
    webhookUrl?: string;
    modelConfig?: object;
    summary?: {
      enabled: boolean;
      prompt?: string;
    };
  }): void;

  /**
   * - This method can be used to stop the ongoing real-time transcription.
   *
   * - All participants, including the local participant, will receive the {@link transcriptionEvents.TRANSCRIPTION_STOPPING | TRANSCRIPTION_STOPPING} state in the {@link MeetingEvent.transcription-state-changed | transcription-state-changed} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopTranscription();
   * ```
   */
  stopTranscription(): void;

  /**
   * - This method can be used to start recording the meeting.
   *
   * - All participants, including the local participant, will receive the {@link recordingEvents.RECORDING_STARTING | RECORDING_STARTING} event state in the {@link MeetingEvent.recording-state-changed | recording-state-changed} event.
   *
   *
   * @param config Recording configuration options.
   *
   * @param config.layout
   * Defines how participants are arranged in the recording.
   *
   * @param config.layout.type
   * Layout type for the recording.
   *
   * @param config.layout.priority
   * Determines participant prioritization.
   *
   * @param config.layout.gridSize
   * Maximum number of participants displayed simultaneously.
   *
   * @param config.theme
   * Visual theme applied to the recording.
   *
   * @param config.mode
   * Defines whether the recording includes video or audio only.
   *
   * @param config.quality
   * Controls the output quality of the recording.
   *
   * @param webhookUrl
   * Webhook URL triggered when the recording state changes.
   *
   * @param awsDirPath
   * Path to the directory in your S3 bucket where recordings are stored.
   *
   * @param transcription
   * Configuration for post-recording transcription and summary generation.
   *
   * @param transcription.enabled
   * Enables or disables transcription.
   *
   * @param transcription.summary.enabled
   * Enables or disables summary generation.
   *
   * @param transcription.summary.prompt
   * Custom prompt used for generating transcription summaries.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const webhookUrl = "https://webhook.your-api-server.com";
   *
   * const awsDirPath = "/meeting-recordings/";
   *
   * const config = {
   *   layout: {
   *     type: "SPOTLIGHT",
   *     priority: "PIN",
   *     gridSize: 9,
   *   },
   *   theme: "DEFAULT",
   * };
   *
   * const transcription = {
   *   enabled: true,
   *   summary: {
   *     enabled: true,
   *   },
   * };
   *
   * meeting?.startRecording(config, webhookUrl, awsDirPath, transcription);
   * ```
   */
  startRecording(
    config?: {
      layout?: {
        type?: "GRID" | "SPOTLIGHT" | "SIDEBAR";
        priority?: "SPEAKER" | "PIN";
        gridSize?: number;
      };
      theme?: "DARK" | "LIGHT" | "DEFAULT";
      mode?: "video-and-audio" | "audio";
      quality?: "low" | "med" | "high";
    },
    webhookUrl?: string,
    awsDirPath?: string,
    transcription?: {
      enabled: boolean;
      summary?: {
        enabled: boolean;
        prompt?: string;
      };
    }
  ): void;

  /**
   * - This method can be used to stop the ongoing meeting recording.
   *
   * - All participants, including the local participant, will receive the {@link recordingEvents.RECORDING_STOPPING | RECORDING_STOPPING} event state in the {@link MeetingEvent.recording-state-changed | recording-state-changed} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopRecording();
   * ```
   */
  stopRecording(): void;

  /**
   * - This method can be used to start live streaming the meeting.
   * - This allows you to stream the meeting to external platforms such as YouTube, Facebook, or any service that supports **RTMP**.
   * - All participants, including the local participant, will receive the {@link livestreamEvents.LIVESTREAM_STARTING | LIVESTREAM_STARTING} state in the {@link MeetingEvent.livestream-state-changed | livestream-state-changed} event.
   *
   * @param outputs
   * An array of RTMP output destinations where the livestream will be broadcast.
   *
   * @param config
   * Configuration options for the RTMP livestream.
   *
   * @param config.layout.type
   * Defines the layout used for the livestream.
   *
   * @param config.layout.priority
   * Determines participant priority when composing the livestream layout.
   *
   * @param config.layout.gridSize
   * Specifies the maximum number of participants displayed in the grid.
   *
   * @param config.theme
   * Defines the color theme of the livestream.
   *
   * @param config.recording
   * This can be used to enable or disable recording.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const outputs = [
   *   {
   *     url: "rtmp://a.rtmp.youtube.com/live2",
   *     streamKey: "<STREAM_KEY>",
   *   },
   *   {
   *     url: "rtmps://",
   *     streamKey: "<STREAM_KEY>",
   *   },
   * ];
   *
   * const config = {
   *   layout: {
   *     type: "SPOTLIGHT",
   *     priority: "PIN",
   *     gridSize: 9,
   *   },
   *   theme: "DEFAULT",
   *   recording: {
   *     enabled: true,
   *   },
   * };
   *
   * meeting?.startLivestream(outputs, config);
   * ```
   */
  startLivestream(
    outputs: Array<{
      url: string;
      streamKey: string;
    }>,
    config?: {
      layout?: {
        type?: "GRID" | "SPOTLIGHT" | "SIDEBAR";
        priority?: "SPEAKER" | "PIN";
        gridSize?: number;
      };
      theme?: "DARK" | "LIGHT" | "DEFAULT";
      recording?: {
        enabled: boolean;
      };
    }
  ): void;

  /**
   * - This method can be used to stop the ongoing livestream.
   * - All participants, including the local participant, will receive the {@link livestreamEvents.LIVESTREAM_STOPPING | LIVESTREAM_STOPPING} state in the {@link MeetingEvent.livestream-state-changed | livestream-state-changed} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopLivestream();
   * ```
   */
  stopLivestream(): void;

  /**
   * - This method can be used to start HLS streaming for the meeting.
   * - This allows participants and viewers to watch the meeting via HLS playback.
   * - All participants, including the local participant, will receive the {@link hlsEvents.HLS_STARTING | HLS_STARTING} event state in the {@link MeetingEvent.hls-state-changed | hls-state-changed} event.
   *
   * @param config Configuration used to control the HLS stream.
   *
   * @param config.layout.type
   * Defines the layout used in the HLS stream.
   *
   * @param config.layout.priority
   * Determines participant priority when composing the layout.
   *
   * @param config.layout.gridSize
   * Specifies the maximum number of participants shown in the grid.
   *
   * @param config.theme
   * Defines the visual theme of the HLS stream.
   *
   * @param config.mode
   * Determines whether the stream includes video and audio or audio only.
   *
   * @param config.quality
   * Defines the output video quality of the HLS stream.
   *
   * @param config.recording
   * This can be used to enable or disable recording.
   *
   * @param transcription
   * Configuration for post-meeting transcription and summary generation.
   *
   * @param transcription.enabled
   * Enables or disables transcription.
   *
   * @param transcription.summary.enabled
   * Enables or disables summary generation.
   *
   * @param transcription.summary.prompt
   * Custom prompt used for generating the summary.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const config = {
   *   layout: {
   *     type: "SPOTLIGHT",
   *     priority: "PIN",
   *     gridSize: 9,
   *   },
   *   theme: "DEFAULT",
   *   recording : {
   *     enabled: true,
   *   };
   * };
   *
   * const transcription = {
   *   enabled: true,
   *   summary: {
   *     enabled: true,
   *   },
   * };
   *
   * meeting?.startHls(config, transcription);
   * ```
   */
  startHls(
    config?: {
      layout?: {
        type?: "GRID" | "SPOTLIGHT" | "SIDEBAR";
        priority?: "SPEAKER" | "PIN";
        gridSize?: number;
      };
      theme?: "DARK" | "LIGHT" | "DEFAULT";
      mode?: "video-and-audio" | "audio";
      quality?: "low" | "med" | "high";
      recording?: {
        enabled: boolean;
      };
    },
    transcription?: {
      enabled: boolean;
      summary?: {
        enabled: boolean;
        prompt?: string;
      };
    }
  ): Promise<void>;

  /**
   * - This method can be used to stop the active HLS stream.
   * - All participants, including the local participant, will receive the {@link hlsEvents.HLS_STOPPING | HLS_STOPPING} event state in the {@link MeetingEvent.hls-state-changed | hls-state-changed} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopHls();
   * ```
   */
  stopHls(): void;

  /**
   * - This method can be used to retrieve all available microphone devices connected to the system.
   *
   * @returns
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const handleGetMics = async () => {
   *   const mics = await meeting?.getMics();
   *   console.log(mics);
   * };
   *
   * handleGetMics();
   * ```
   */
  getMics(): Promise<
    Array<{
      deviceId: string;
      label: string;
    }>
  >;

  /**
   * - This method can be used to retrieve all available camera devices connected to the system.
   *
   * @returns
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const handleGetWebcams = async () => {
   *   const webcams = await meeting?.getWebcams();
   *   console.log(webcams);
   * };
   *
   * handleGetWebcams();
   * ```
   */
  getWebcams(): Promise<
    Array<{
      deviceId: string;
      label: string;
      facingMode: "front" | "environment";
    }>
  >;

  /**
   * - This method can be used to enable Adaptive Subscription.
   * - Adaptive Subscription dynamically adjusts which video streams are subscribed to, based on participant visibility and current network conditions.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.enableAdaptiveSubscription();
   * ```
   */
  enableAdaptiveSubscription(): void;

  /**
   * - This method can be used to disable Adaptive Subscription.
   * - When disabled, all video streams remain subscribed regardless of visibility or network conditions.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.disableAdaptiveSubscription();
   * ```
   */
  disableAdaptiveSubscription(): void;

  /**
   * - This method can be used to switch the current session to another meeting without disconnecting.
   * - This allows a seamless transition between meetings while preserving the active session context.
   *
   * @param options Configuration for switching meetings.
   *
   * @param options.meetingId
   * The ID of the meeting to switch to.
   *
   * @param options.token
   * Authentication token for the destination meeting.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.switchTo({
   *   meetingId: "new-meeting-id",
   *   token: "optional-auth-token",
   * });
   * ```
   */
  switchTo(options: { meetingId: string; token?: string }): void;

  /**
   * - This method can be used to start relaying selected media streams from the current meeting to another destination meeting.
   * - Once the relay is successfully initiated, the local participant receives the {@link MeetingEvent.media-relay-started | media-relay-started} event.
   *
   * @param options Configuration for media relay.
   *
   * @param options.destinationMeetingId
   * The ID of the destination meeting where media will be relayed.
   *
   * @param options.token
   * Authentication token for the destination meeting.
   *
   * @param options.kinds
   * Specifies which media tracks should be relayed.
   *
   * @returns
   * A promise that resolves once the relay request is successfully processed.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.requestMediaRelay({
   *   destinationMeetingId: "destination-meeting-id",
   *   token: "auth-token",
   *   kinds: ["audio", "video"],
   * });
   * ```
   */
  requestMediaRelay(options: {
    destinationMeetingId: string;
    token?: string;
    kinds?: Array<"audio" | "video" | "share">;
  }): Promise<void>;

  /**
   * - This method can be used to stop the ongoing media relay to a destination meeting.
   * - Once stopped, the local participant will receive the {@link MeetingEvent.media-relay-stopped | media-relay-stopped} event.
   *
   * @param destinationMeetingId
   * The ID of the destination meeting where media relay should be stopped.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopMediaRelay("destination-meeting-id");
   * ```
   */
  stopMediaRelay(destinationMeetingId: string): Promise<void>;

  /**
   * - This method can be used to pause active media streams in the meeting.
   * - The local participant will receive the {@link MeetingEvent.paused-all-streams | paused-all-streams} event.
   *
   * @param kind
   * Specifies which type of media stream should be paused. If not provided, **all media streams** (audio, video, and screen share) will be paused.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.pauseAllStreams("video");
   * ```
   */
  pauseAllStreams(
    kind?: "audio" | "video" | "shareAudio" | "share" | "all"
  ): void;

  /**
   * - This method can be used to resume media streams that were previously paused.
   * - The local participant will receive the {@link MeetingEvent.resumed-all-streams | resumed-all-streams} event.
   *
   * @param kind
   * Specifies which type of media stream should be resumed.If not provided, **all media streams** (audio, video, and screen share) will be resumed.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.resumeAllStreams("video");
   * ```
   */
  resumeAllStreams(
    kind?: "audio" | "video" | "shareAudio" | "share" | "all"
  ): void;

  /**
   * - This method can be used to change the active microphone device.
   * - If multiple microphones are available, this method allows switching between them dynamically during the meeting.
   *
   * @param object
   * Either:
   * - A `deviceId` string of the microphone to switch to, or
   * - A `MediaStream` to be used as the audio input source.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const mics = await meeting?.getMics();
   *
   * const { deviceId, label } = mics[0];
   *
   * meeting?.changeMic(deviceId);
   * ```
   */
  changeMic(object: string | MediaStream): void;

  /**
   * - This method can be used to change the active webcam device.
   * - If multiple cameras are connected, this method allows switching between them dynamically during the meeting.
   *
   * @param object
   * Either:
   * - A `deviceId` of the webcam to switch to, or
   * - A `MediaStream` to be used as the video source.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const webcams = await meeting?.getWebcams();
   *
   * const { deviceId, label } = webcams[0];
   *
   * meeting?.changeWebcam(deviceId);
   * ```
   */
  changeWebcam(object: string | MediaStream): void;

  /**
   * - This method can be used to set the webcam video quality for the local participant.
   * - This method allows you to dynamically adjust the outgoing webcam video quality during the meeting.
   *
   * @param quality
   * Specifies the desired webcam quality.
   *
   * **Allowed values:**
   * - `"low"` – Low video quality
   * - `"med"` – Medium video quality
   * - `"high"` – High video quality
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.setWebcamQuality("high");
   * ```
   */
  setWebcamQuality(quality: "low" | "med" | "high"): void;

  /**
   * - This method can be used to start the whiteboard session.
   * - All participants, including the local participant, will receive the {@link MeetingEvent.whiteboard-started | whiteboard-started} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.startWhiteboard();
   * ```
   */
  startWhiteboard(): Promise<void>;

  /**
   * - This method can be used to stop the ongoing whiteboard session.
   * - All participants, including the local participant, will receive the {@link MeetingEvent.whiteboard-stopped | whiteboard-stopped} event.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * meeting?.stopWhiteboard();
   * ```
   */
  stopWhiteboard(): Promise<void>;

  /**
   * - This method can be used to upload a file to VideoSDK's temporary storage.
   * - This method returns a `fileUrl`, which can later be used to retrieve the uploaded file.
   *
   * @param options
   *
   * @param options.base64Data
   * Base64-encoded representation of the file.
   *
   * @param options.token
   * VideoSDK authentication token. Learn more about tokens [here](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/authentication-and-token).
   *
   * @param options.fileName
   * Name of the file including its extension.
   *
   * @example
   * ```ts
   * const fileUrl = await meeting.uploadBase64File({
   *   base64Data: "<BASE64_DATA>", // Convert your file to base64 and pass here
   *   token: "<VIDEOSDK_TOKEN>",
   *   fileName: "image.jpeg", // Provide name with extension here,
   * });
   *
   * console.log("File URL:", fileUrl);
   * ```
   */
  uploadBase64File(options: {
    base64Data: string;
    token: string;
    fileName: string;
  }): Promise<string | null>;

  /**
   * - This method can be used to retrieve a previously uploaded file from VideoSDK's temporary storage.
   * - The returned value is a Base64-encoded string.
   *
   * @param options
   *
   * @param options.url
   * The file URL returned by {@link uploadBase64File | uploadBase64File()}.
   *
   * @param options.token
   * VideoSDK authentication token.
   *
   * @returns A Base64-encoded string of the requested file.
   *
   * @example
   * ```ts
   * let meeting;
   *
   * // Initialize Meeting
   * meeting = VideoSDK.initMeeting({
   *   // ...
   * });
   *
   * const base64 = await meeting.fetchBase64File({
   *   url: "<FILE_URL>", // Provide fileUrl which is returned by uploadBase64File(),
   *   token: "<VIDEOSDK_TOKEN>",
   * });
   *
   * console.log("Base64:", base64);
   * ```
   */
  fetchBase64File(options: {
    url: string;
    token: string;
  }): Promise<string | null>;

  /**
   * Registers an event listener.
   * @param eventType Event name to which you want to subscribe.
   * @param listener Callback function which will be triggered when the event happens
   *
   * To view the complete list of available events and their details, refer to {@link MeetingEvent}.
   */
  on(
    eventType:
      | "participant-joined"
      | "participant-left"
      | "participant-mode-change"
      | "speaker-changed"
      | "presenter-changed"
      | "main-participant-changed"
      | "entry-requested"
      | "entry-responded"
      | "recording-state-changed"
      | "livestream-state-changed"
      | "hls-state-changed"
      | "whiteboard-started"
      | "whiteboard-stopped"
      | "meeting-joined"
      | "meeting-left"
      | "mic-requested"
      | "webcam-requested"
      | "pin-state-changed"
      | "meeting-state-changed"
      | "error"
      | "transcription-state-changed"
      | "transcription-text"
      | "paused-all-streams"
      | "resumed-all-streams"
      | "media-relay-started"
      | "media-relay-stopped"
      | "media-relay-error"
      | "media-relay-request-response"
      | "media-relay-request-received",
    listener: (data: any) => void
  ): void;

  /**
   * Removes an event listener that was previously registered.
   * @param eventType Event name to which you want to unsubscribe.
   * @param listener Callback function which was passed while subscribing to the event
   *
   * To view the complete list of available events and their details, refer to {@link MeetingEvent}.
   */
  off(
    eventType:
      | "participant-joined"
      | "participant-left"
      | "participant-mode-change"
      | "speaker-changed"
      | "presenter-changed"
      | "main-participant-changed"
      | "entry-requested"
      | "entry-responded"
      | "recording-state-changed"
      | "livestream-state-changed"
      | "hls-state-changed"
      | "whiteboard-started"
      | "whiteboard-stopped"
      | "meeting-joined"
      | "meeting-left"
      | "mic-requested"
      | "webcam-requested"
      | "pin-state-changed"
      | "meeting-state-changed"
      | "error"
      | "transcription-state-changed"
      | "transcription-text"
      | "paused-all-streams"
      | "resumed-all-streams"
      | "media-relay-started"
      | "media-relay-stopped"
      | "media-relay-error"
      | "media-relay-request-response"
      | "media-relay-request-received",
    listener: (data: any) => void
  ): void;
}

export type MeetingEvent = {
  /**
   * @event
   *
   * - Triggered when a new participant joins the meeting.
   *
   * @param participant
   * The `Participant` instance representing the newly joined participant.
   *
   * @example
   * ```ts
   * meeting.on("participant-joined", (participant) => {
   *   //
   * });
   * ```
   * @returns
   */
  "participant-joined": (participant: Participant) => void;

  /**
   * @event
   *
   * - Triggered when a participant leaves the meeting.
   * - When this event is emitted, a `reason` object is provided that describes why the participant left.
   *
   * **Possible reason codes:**
   *
   * | Reason | Code | Description |
   * |--------|------|-------------|
   * | WEBSOCKET_DISCONNECTED | 1001 | Socket disconnected |
   * | REMOVE_PEER | 1002 | Participant was removed from the meeting |
   * | REMOVE_PEER_VIEWER_MODE_CHANGED | 1003 | Participant removed because viewer mode was changed |
   * | REMOVE_PEER_MEDIA_RELAY_STOP | 1004 | Participant removed because media relay was stopped |
   * | SWITCH_ROOM | 1005 | Participant switched to a different room |
   * | ROOM_CLOSE | 1006 | The meeting has been closed |
   * | UNKNOWN | 1007 | Participant disconnected due to an unknown reason |
   * | REMOVE_ALL | 1008 | Remove All from the meeting |
   * | MEETING_END_API | 1009 | Meeting Ended. |
   * | REMOVE_PEER_API | 1010 | Participant removed from the meeting |
   * | DUPLICATE_PARTICIPANT | 1011 | Leaving meeting, since this participantId joined from another device. |
   * | MANUAL_LEAVE_CALLED | 1101 | Participant manually called the leave() method to exit the meeting |
   * | WEBSOCKET_CONNECTION_ATTEMPTS_EXHAUSTED | 1102 | Meeting left after multiple failed websocket connection attempts. |
   * | JOIN_ROOM_FAILED | 1103 | Meeting left due to an error while joining the room. |
   * | SWITCH_ROOM_FAILED | 1104 | Meeting left due to an error while switching rooms. |
   *
   * @param participant
   * The `Participant` instance who left the meeting.
   *
   * @param reason
   * An object describing the reason and corresponding code.
   *
   * @example
   * ```ts
   * meeting.on("participant-left", (participant, reason) => {
   *   if (reason.code === Constants.leaveReason.MANUAL_LEAVE_CALLED) {
   *     // Handle manual leave
   *   }
   * });
   * ```
   */
  "participant-left": (participant: Participant, reason: object) => void;

  /**
   * @event
   *
   * - Triggered when a participant’s mode changes.
   *
   * @param options
   *
   * @param options.participantId ID of the participant whose mode has changed.
   *
   * @param options.mode The new mode of the participant. Possible values are defined in {@link modes}.
   *
   * @example
   * ```ts
   * meeting.on("participant-mode-changed", ({ participantId, mode }) => {
   *   console.log(`${participantId} changed mode to ${mode}`);
   * });
   * ```
   * @returns
   */
  "participant-mode-changed": (options: {
    participantId: string;
    mode: string;
  }) => void;

  /**
   * @event
   *
   * - Triggered when the active speaker changes.
   * - If no participant is actively speaking, `null` is returned.
   *
   * @param activeSpeakerId
   * ID of the currently active speaker, or `null` if no one is speaking.
   *
   * @example
   * ```ts
   * meeting.on("speaker-changed", (activeSpeakerId) => {
   *   //
   * });
   * ```
   */
  "speaker-changed": (activeSpeakerId: string | null) => void;

  /**
   * @event
   *
   * - Triggered when a participant starts or stops screen sharing.
   * - If screen sharing stops, the callback receives `null`.
   *
   * @param activePresenterId
   * ID of the participant currently presenting, or `null` if no one is presenting.
   *
   * @example
   * ```ts
   * meeting.on("presenter-changed", (activePresenterId) => {
   *   //
   * });
   * ```
   */
  "presenter-changed": (activePresenterId: string | null) => void;

  /**
   * @event
   *
   * - Triggered when a participant requests to join the meeting and their token includes the `ask_join` permission.
   * - This event is emitted **only** to participants whose token includes the `allow_join` permission.
   *
   * @param data Event payload containing participant details and actions.
   *
   * @param data.participantId
   * Unique ID of the participant requesting to join the meeting.
   *
   * @param data.name
   * Display name of the participant requesting to join.
   *
   * @param data.allow
   * Call this function to allow the participant to join the meeting.
   *
   * @param data.deny
   * Call this function to deny the participant’s request.
   *
   * @returns
   * @example
   * ```ts
   * meeting.on("entry-requested", (data) => {
   *   const { participantId, name, allow, deny } = data;
   *
   *   console.log(`${name} requested to join the meeting`);
   *
   *   // Allow the participant
   *   allow();
   *
   *   // Or deny the request
   *   deny();
   * });
   * ```
   */
  "entry-requested": (data: {
    allow: Function;
    deny: Function;
    name: string;
    participantId: string;
  }) => void;

  /**
   * @event
   *
   * - Triggered when a participant’s `join()` request is responded to with an allow or deny decision.
   *
   * This event is emitted to:
   * - All participants whose token includes the `allow_join` permission.
   * - The participant who requested to join the meeting.
   *
   * @param participantId
   * ID of the participant who requested to join the meeting.
   *
   * @param decision
   * The final decision for the join request.
   *
   * **Possible values:**
   * - `"allowed"` – The participant was allowed to join.
   * - `"denied"` – The participant was denied entry.
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("entry-responded", (participantId, decision) => {
   *   // participantId will be id of participant who requested to join meeting
   *
   *   if (decision === "allowed") {
   *     console.log("Participant allowed");
   *   } else {
   *     console.log("Participant denied");
   *   }
   * });
   * ```
   */
  "entry-responded": (
    participantId: string,
    decision: "allowed" | "denied"
  ) => void;

  /**
   * @event
   *
   * - Triggered when the main participant in the meeting changes.
   *
   * @param participant The `Participant` instance who is now the main participant.
   *
   * @example
   * ```
   * meeting.on("main-participant-changed", (participant) => {
   *   //
   * });
   * ```
   */
  "main-participant-changed": (participant: Participant) => void;

  /**
   * @event
   *
   * - Triggered when the meeting’s recording state changes.
   *
   * @param data
   *
   * @param data.status
   * The current recording state:
   *
   * - `RECORDING_STARTING` - Recording is in starting phase and hasn't started yet.
   * - `RECORDING_STARTED` - Recording has started successfully.
   * - `RECORDING_STOPPING` - Recording is in stopping phase and hasn't stopped yet.
   * - `RECORDING_STOPPED` - Recording has stopped successfully.
   *
   * @returns
   *
   * @example
   * ```ts
   * import { VideoSDK } from "@videosdk.live/js-sdk";
   *
   * const Constants = VideoSDK.Constants;
   *
   * meeting.on("recording-state-changed", (data) => {
   *   const { status } = data;
   *
   *   if (status === Constants.recordingEvents.RECORDING_STARTING) {
   *     console.log("Meeting recording is starting");
   *   } else if (status === Constants.recordingEvents.RECORDING_STARTED) {
   *     console.log("Meeting recording is started");
   *   } else if (status === Constants.recordingEvents.RECORDING_STOPPING) {
   *     console.log("Meeting recording is stopping");
   *   } else if (status === Constants.recordingEvents.RECORDING_STOPPED) {
   *     console.log("Meeting recording is stopped");
   *   } else {
   *   //
   *   }
   * });
   * ```
   */
  "recording-state-changed": (data: { status: string }) => void;

  /**
   * @event
   *
   * - Triggered when the meeting’s livestream state changes.
   *
   * @param data
   *
   * @param data.status
   * Possible values:
   * - `LIVESTREAM_STARTING` - Livestream is in starting phase and hasn't started yet.
   * - `LIVESTREAM_STARTED` - Livestream has started successfully.
   * - `LIVESTREAM_STOPPING` - Livestream is in stopping phase and hasn't stopped yet.
   * - `LIVESTREAM_STOPPED` - Livestream has stopped successfully.
   *
   * @returns
   *
   * @example
   * ```ts
   * import { VideoSDK } from "@videosdk.live/js-sdk";
   *
   * const Constants = VideoSDK.Constants;
   *
   * meeting.on("livestream-state-changed", (data) => {
   *   const { status } = data;
   *
   *   if (status === Constants.livestreamEvents.LIVESTREAM_STARTING) {
   *     console.log("Meeting livestream is starting");
   *   } else if (status === Constants.livestreamEvents.LIVESTREAM_STARTED) {
   *     console.log("Meeting livestream is started");
   *   } else if (status === Constants.livestreamEvents.LIVESTREAM_STOPPING) {
   *     console.log("Meeting livestream is stopping");
   *   } else if (status === Constants.livestreamEvents.LIVESTREAM_STOPPED) {
   *     console.log("Meeting livestream is stopped");
   *   } else {
   *   //
   *   }
   * });
   * ```
   */
  "livestream-state-changed": (data: { status: string }) => void;

  /**
   * @event
   *
   * - Triggered when the HLS (HTTP Live Streaming) state changes.
   *
   * @param data
   *
   * @param data.status
   * Possible values:
   * - `HLS_STARTING` - Hls is in starting phase and hasn't started yet.
   * - `HLS_STARTED`- Hls has started successfully will return playbackHlsUrl and livestreamUrl.
   * - `HLS_PLAYABLE` - Hls has started and the playbackHlsUrl and livestreamUrl is now playable.
   * - `HLS_STOPPING` - Hls is in stopping phase and hasn't stopped yet.
   * - `HLS_STOPPED`- Hls has stopped successfully.
   *
   * @param data.playbackHlsUrl Live HLS with playback support
   *
   * @param data.livestreamUrl Live HLS without playback support
   *
   * @returns
   *
   * @example
   * ```ts
   * import { VideoSDK } from "@videosdk.live/js-sdk";
   *
   * const Constants = VideoSDK.Constants;
   *
   * meeting.on("hls-state-changed", (data) => {
   *   const { status } = data;
   *
   *   if (status === Constants.hlsEvents.HLS_STARTING) {
   *     console.log("Meeting Hls is starting");
   *   } else if (status === Constants.hlsEvents.HLS_STARTED) {
   *     // when hls is started you will receive playbackHlsUrl
   *     const { playbackHlsUrl } = data;
   *     console.log("Meeting Hls is started");
   *   } else if (status === Constants.hlsEvents.HLS_STOPPING) {
   *     console.log("Meeting Hls is stopping");
   *   } else if (status === Constants.hlsEvents.HLS_STOPPED) {
   *     console.log("Meeting Hls is stopped");
   *   } else {
   *     //
   *   }
   * });
   * ```
   */
  "hls-state-changed": (data: {
    status: string;
    playbackHlsUrl: string;
    livestreamUrl: string;
  }) => void;

  /**
   * @event
   *
   * - Triggered when the whiteboard is successfully started.
   * - This event provides the URL of the active whiteboard session.
   *
   * @param data
   *
   * @param data.url
   * URL of the whiteboard session.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("whiteboard-started", (data) => {
   *   const { url } = data;
   *   // Use the whiteboard URL
   * });
   * ```
   */
  "whiteboard-started": (data: { url: string }) => void;

  /**
   * @event
   *
   * - Triggered when the whiteboard session is stopped for all participants.
   *
   * @example
   * ```ts
   * meeting.on("whiteboard-stopped", () => {
   *   // Whiteboard session stopped
   * });
   * ```
   */
  "whiteboard-stopped": () => void;

  /**
   * @event
   * - This event will be emitted to the participant `B` when any other participant `A` requests to enable mic of participant `B`.
   * - On accepting the request, mic of participant `B` will be enabled.
   *
   * @param data
   *
   * @param data.participantId
   * ID of the participant who requested to enable your microphone.
   *
   * @param data.accept
   * Call this function to accept the request and enable your microphone.
   *
   * @param data.reject
   * Call this function to reject the request.
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("mic-requested", (data) => {
   *   const { participantId, accept, reject } = data;
   *
   *   // Accept the request
   *   accept();
   *
   *   // Or reject the request
   *   reject();
   * });
   * ```
   */
  "mic-requested": (data: {
    accept: Function;
    participantId: string;
    reject: Function;
  }) => void;

  /**
   * @event
   * - This event will be emitted to the participant `B` when any other participant `A` requests to enable webcam of participant `B`.
   * - On accepting the request, webcam of participant `B` will be enabled.
   *
   * @param data
   *
   * @param data.participantId
   * ID of the participant who requested to enable your webcam.
   *
   * @param data.accept
   * Call this function to accept the request and enable your webcam.
   *
   * @param data.reject
   * Call this function to reject the request.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("webcam-requested", (data) => {
   *   const { participantId, accept, reject } = data;
   *
   *   // Accept the request
   *   accept();
   *
   *   // Or reject the request
   *   reject();
   * });
   * ```
   */
  "webcam-requested": (data: {
    accept: Function;
    participantId: string;
    reject: Function;
  }) => void;

  /**
   * @event
   *
   * - Triggered when the local participant successfully joins the meeting.
   *
   * @example
   * ```js
   * meeting.on("meeting-joined", () => {
   *   // Participant has joined the meeting
   * });
   * ```
   */
  "meeting-joined": () => void;

  /**
   * @event
   *
   * - Triggered when the local participant leaves the meeting.
   * - When this event is emitted, a `reason` object is also provided that explains why the participant left the meeting.
   *
   * The table below lists the possible reason codes:
   *
   * | **Reason** | **Code** | **Description** |
   * |---------|------|-------------|
   * | WEBSOCKET_DISCONNECTED | 1001 | Socket disconnected |
   * | REMOVE_PEER | 1002 | Participant was removed from the meeting |
   * | REMOVE_PEER_VIEWER_MODE_CHANGED | 1003 | Participant removed due to viewer mode change |
   * | REMOVE_PEER_MEDIA_RELAY_STOP | 1004 | Participant removed because media relay was stopped |
   * | SWITCH_ROOM | 1005 | Participant switched to another room |
   * | ROOM_CLOSE | 1006 | The meeting was closed |
   * | UNKNOWN | 1007 | Participant disconnected due to an unknown reason |
   * | REMOVE_ALL | 1008 | All participants were removed |
   * | MEETING_END_API | 1009 | Meeting ended programmatically |
   * | REMOVE_PEER_API | 1010 | Participant removed via API |
   * | DUPLICATE_PARTICIPANT | 1011 | Participant joined from another device |
   * | MANUAL_LEAVE_CALLED | 1101 | Participant manually left the meeting |
   * | WEBSOCKET_CONNECTION_ATTEMPTS_EXHAUSTED | 1102 | WebSocket connection retries exhausted |
   * | JOIN_ROOM_FAILED | 1103 | Failed to join the meeting |
   * | SWITCH_ROOM_FAILED | 1104 | Failed to switch rooms |
   *
   * @param reason
   * Object containing the reason and corresponding code.
   *
   * @returns
   *
   * @example
   * ```js
   * meeting.on("meeting-left", (reason) => {
   *   if (reason.code === Constants.leaveReason.MANUAL_LEAVE_CALLED) {
   *     // Handle manual leave
   *   }
   * });
   * ```
   */
  "meeting-left": (reason: object) => void;
  /**
   * @event
   *
   * - Triggered when the pin state of a participant changes.
   * - This event is emitted for all participants whenever a participant is pinned or unpinned.
   *
   * @param data
   *
   * @param data.peerId
   * ID of the participant whose pin state changed.
   *
   * @param data.state
   * Current pin state (`true` if pinned, `false` if unpinned).
   *
   * @param data.pinnedBy
   * ID of the participant who performed the pin or unpin action.
   *
   * @example
   * ```js
   * meeting.on("pin-state-changed", (data) => {
   *   const { peerId, state, pinnedBy } = data;
   *   console.log("Pin state changed:", peerId, state, pinnedBy);
   * });
   * ```
   */
  "pin-state-changed": (data: {
    peerId: string;
    state: boolean;
    pinnedBy: string;
  }) => void;

  /**
   * @event
   *
   * - Triggered whenever the meeting state changes.
   *
   * @param data
   *
   * @param data.state
   * The current meeting state. Possible values:
   * - `CONNECTING`
   * - `CONNECTED`
   * - `RECONNECTING`
   * - `DISCONNECTED`
   * - `FAILED`
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("meeting-state-changed", (data) => {
   *   const { state } = data;
   *
   *   switch (state) {
   *     case "CONNECTING":
   *       console.log("Meeting is connecting");
   *       break;
   *     case "CONNECTED":
   *       console.log("Meeting is connected");
   *       break;
   *     case "DISCONNECTED":
   *       console.log("Meeting disconnected");
   *       break;
   *     case "RECONNECTING":
   *       console.log("Reconnecting to meeting");
   *       break;
   *     case "FAILED":
   *       console.log("Meeting failed");
   *       break;
   *     default:
   *       console.log("Unknown state:", state);
   *   }
   * });
   * ```
   */
  "meeting-state-changed": (data: { state: string }) => void;

  /**
   * @event
   *
   * - Triggered when an error occurs during the meeting lifecycle.
   * - The event provides an error code and a descriptive message. Refer to {@link Errors} for a complete list of supported error codes.
   *
   * @param data
   *
   * @param data.code
   * Numeric error code representing the type of error.
   *
   * @param data.message
   * Human-readable description of the error.
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("error", (data) => {
   *   const { code, message } = data;
   *   console.error(`Error (${code}): ${message}`);
   * });
   * ```
   */
  error: (data: { code: number; message: string }) => void;

  /**
   * @event
   *
   * - Triggered when the state of realtime transcription changes.
   *
   * @param data
   *
   * @param data.id
   * ID of the transcription session.
   *
   * @param data.status
   * `status` has following values:
   * - `TRANSCRIPTION_STARTING` - Realtime Transcription is in starting phase and hasn't started yet.
   * - `TRANSCRIPTION_STARTED` - Realtime Transcription has started successfully.
   * - `TRANSCRIPTION_STOPPING` - Realtime Transcription is in stopping phase and hasn't stopped yet.
   * - `TRANSCRIPTION_STOPPED` - Realtime Transcription has stopped successfully.
   *
   * @returns
   *
   * @example
   * ```ts
   *
   * import { VideoSDK } from "@videosdk.live/js-sdk";
   *
   * const Constants = VideoSDK.Constants;
   * meeting.on("transcription-state-changed", (data) => {
   *   let { status, id } = data;
   *
   *   if (status === Constants.transcriptionEvents.TRANSCRIPTION_STARTING) {
   *     console.log(`Realtime Transcription with ${id} is starting`);
   *   } else if (status === Constants.transcriptionEvents.TRANSCRIPTION_STARTED) {
   *     console.log(`Realtime Transcription with ${id} is started`);
   *   } else if (status === Constants.transcriptionEvents.TRANSCRIPTION_STOPPING) {
   *     console.log(`Realtime Transcription with ${id} is stopping`);
   *   } else if (status === Constants.transcriptionEvents.TRANSCRIPTION_STOPPED) {
   *     console.log(`Realtime Transcription with ${id} is stopped`);
   *   }
   * });
   * ```
   */
  "transcription-state-changed": (data: { status: string; id: string }) => void;

  /**
   * @event
   *
   * - Triggered when realtime transcription text is received.
   *
   * @param data
   *
   * @param data.participantId
   * ID of the participant whose speech was transcribed.
   *
   * @param data.participantName
   * Name of the participant whose speech was transcribed.
   *
   * @param data.text
   * Transcribed text content.
   *
   * @param data.timestamp
   * Timestamp (in milliseconds since epoch) when the transcription was generated.
   *
   * @param data.type
   * Type of transcription event.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("transcription-text", (data) => {
   *   const { participantName, text, timestamp, type} = data;
   *   console.log(`${participantName}: ${text}`);
   * });
   * ```
   */
  "transcription-text": (data: {
    participantId: string;
    participantName: string;
    text: string;
    timestamp: number;
    type: string;
  }) => void;

  /**
   * @event
   *
   * - Triggered when all or specific media streams are paused.
   *
   * @param data
   *
   * @param data.kind
   * Indicates which media type was paused:
   * - `"audio"` – Audio streams
   * - `"video"` – Video streams
   * - `"share"` – Screen-share video streams
   * - `"shareAudio"` – Screen-share audio streams
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("paused-all-streams", (data) => {
   *   const { kind } = data;
   * });
   * ```
   */
  "paused-all-streams": (data: { kind: string }) => void;

  /**
   * @event
   *
   * - Triggered when paused media streams are resumed.
   *
   * @param data
   *
   * @param data.kind
   * Indicates which media type was resumed:
   * - `"audio"` – Audio streams
   * - `"video"` – Video streams
   * - `"share"` – Screen-share video streams
   * - `"shareAudio"` – Screen-share audio streams
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("resumed-all-streams", (data) => {
   *   const { kind } = data;
   * });
   * ```
   */
  "resumed-all-streams": (data: { kind: string }) => void;

  /**
   * @event
   *
   * - Triggered when a media relay request is received in the destination meeting.
   *
   * @param data
   *
   * @param data.participantId
   * ID of the participant who initiated the media relay request.
   *
   * @param data.meetingId
   * ID of the meeting from which the media relay request originated.
   *
   * @param data.displayName
   * Display name of the participant requesting the media relay.
   *
   * @param data.accept
   * Call this function to accept the media relay request.
   *
   * @param data.reject
   * Call this function to reject the media relay request.
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("media-relay-request-received", ({
   *   participantId,
   *   meetingId,
   *   displayName,
   *   accept,
   *   reject,
   * }) => {
   *   // Handle request
   * });
   * ```
   */
  "media-relay-request-received": (data: {
    participantId: string;
    meetingId: string;
    displayName: string;
    accept: Function;
    reject: Function;
  }) => void;

  /**
   * @event
   *
   * - Triggered when a response is received for a media relay request in the source meeting.
   *
   * @param participantId
   * ID of the participant who responded to the media relay request.
   *
   * @param decision
   * Decision taken for the request.
   *
   * @param decidedBy
   * ID of the participant who decided the decision.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("media-relay-request-response", (participantId, decision) => {
   *   //
   * });
   * ```
   */
  "media-relay-request-response": (
    participantId: string,
    decision: string,
    decidedBy: string
  ) => void;

  /**
   * @event
   *
   * - Triggered when media relay successfully starts for a destination meeting.
   *
   * @param data
   *
   * @param data.meetingId
   * ID of the meeting where the media relay has started.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("media-relay-started", ({ meetingId }) => {
   *   //
   * });
   * ```
   */
  "media-relay-started": (data: { meetingId: string }) => void;

  /**
   * @event
   *
   * - Triggered when media relay stops for a destination meeting.
   *
   * @param data
   *
   * @param data.meetingId
   * ID of the meeting where the media relay stopped.
   *
   * @param data.reason
   * Reason why the media relay stopped.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("media-relay-stopped", ({ meetingId, reason }) => {
   *   //
   * });
   * ```
   */
  "media-relay-stopped": (data: { meetingId: string; reason: string }) => void;

  /**
   * @event
   *
   * - Triggered when an error occurs during media relay.
   *
   * @param meetingId
   * ID of the meeting where the error occurred.
   *
   * @param error
   * Description of the error.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("media-relay-error", (meetingId, error) => {
   *   //
   * });
   * ```
   */
  "media-relay-error": (meetingId: string, error: string) => void;

  /**
   * @event
   *
   * - Triggered when a quality limitation is detected or resolved during the meeting.
   *
   * @param data
   *
   * @param data.type
   * Specifies the type of limitation.
   *
   * @param data.state
   * Indicates whether the limitation is currently active or resolved.
   *
   * @param data.timestamp
   * Time (in milliseconds since epoch) when the event occurred.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("quality-limitation", ({ type, state, timestamp }) => {
   *   //
   * });
   * ```
   */
  "quality-limitation": (data: {
    type: "congestion" | "bandwidth" | "cpu";
    state: "detected" | "resolved";
    timestamp: number;
  }) => void;

  /**
   * @event
   *
   * - Triggered when local microphone silence is detected or resolved.
   * - Useful for detecting muted hardware or when
   *   the local participant's audio track is not capturing any signal.
   *
   * @remarks
   * This event is not emitted on Android Mobile Web browsers.
   *
   * @param data
   *
   * @param data.deviceLabel
   * Label of the microphone track (as reported by the browser).
   *
   * @param data.state
   * Indicates whether silence is currently active or has been resolved.
   * 
   * @param data.timestamp
   * Time (in milliseconds since epoch) when the event occurred.
   * 
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("audio-input-silence", ({ peerId, deviceLabel, state}) => {
   *   //
   * });
   * ```
   */
  "audio-input-silence": (data: {
    deviceLabel?: string;
    state: "detected" | "resolved";
    timestamp: number;
  }) => void;


  /**
   * @event
   *
   * - Triggered whenever a message is received over the DataStream.
   *
   * @param data
   *
   * @param data.payload
   * The received message payload.
   * - `string` for text messages
   * - `Uint8Array` for binary data
   *
   * @param data.from
   * ID of the participant who sent the message.
   *
   * @param data.timestamp
   * Timestamp (in milliseconds since epoch) when the message was sent.
   *
   * @param data.reliability
   * Indicates whether the message delivery was reliable or unreliable.
   *
   * @returns
   *
   * @example
   * ```ts
   * meeting.on("data", (data) => {
   *   const { payload, from, timestamp, reliability } = data;
   * });
   * ```
   */
  data: (data: {
    payload: Uint8Array | string;
    from: string;
    timestamp: number;
    reliability: "reliable" | "unreliable";
  }) => void;
};

import { pubSub } from "./pubSub";
import { realtimeStore } from "./realtimeStore";
import { Participant } from "./participant";
import { CameraDeviceInfo, MicrophoneDeviceInfo } from "./classes/DeviceInfo";
