export enum TranscriptionState {
  TRANSCRIPTION_STARTING = "TRANSCRIPTION_STARTING",
  TRANSCRIPTION_STARTED = "TRANSCRIPTION_STARTED",
  TRANSCRIPTION_STOPPING = "TRANSCRIPTION_STOPPING",
  TRANSCRIPTION_STOPPED = "TRANSCRIPTION_STOPPED",
}
export class Meeting {
  /**
   * @description
   *  This represents the meetingId
   */
  id: string;
  /**
   * @description
   *  This represents the `participantId` of the active speaker in the meeting
   */
  activeSpeakerId?: string;
  /**
   * @description
   *  This represents the `participantId` of the active presenter in the meeting
   */
  activePresenterId?: string;
  /**
   *  @description
   *  This represents the `participantId` of the main participant in the meeting
   */
  mainParticipantId: string;
  /**
   * @deprecated
   */
  connections: Map<string, Connection>;
  /**
   * @description
   *  This represents the `Participant` object for the local participant
   */
  localParticipant: Participant;
  /**
   * @description
   *  This represents the Map of all the Participant objects except local participant
   */
  participants: Map<string, Participant>;
  /**
   * @description
   *  This represents the Map of all the Character Participant objects except normal participant
   */
  characters: Map<string, Character>;
  /**
   * @description This represents the current state of the meeting Livestream
   */
  livestreamState:
    | "LIVESTREAM_STOPPED"
    | "LIVESTREAM_STARTING"
    | "LIVESTREAM_STARTED"
    | "LIVESTREAM_STOPPING";
  /**
   * @description This represents the current state of the meeting recording
   */
  recordingState:
    | "RECORDING_STOPPED"
    | "RECORDING_STARTING"
    | "RECORDING_STARTED"
    | "RECORDING_STOPPING";
  /**
   * @description This represents the current state of the meeting HLS
   *
   */
  hlsState: "HLS_STOPPED" | "HLS_STARTING" | "HLS_STARTED" | "HLS_STOPPING";
  /**
   * @description This object will provide the URLs to play the HLS streams
   */
  hlsUrls: {
    downstreamUrl?: string;
    playbackHlsUrl?: string;
    livestreamUrl?: string;
  };
  /**
   * @description This object will contain all the messages send using the `sendChatMessage` method
   */
  messages: Array<{
    message: string;
    senderId: string;
    senderName: string;
    timestamp: Date;
    topic: string;
    payload: object;
  }>;

  /**
   * @description This represents the current state of the realtime transcription
   *
   */
  transcriptionState: TranscriptionState;

  /**
   * @description This method is used to join the meeting
   */
  join(): void;

  /**
   * @description This method is used to change the participant mode between SEND_AND_RECV, RECV_ONLY and SIGNALLING_ONLY
   */
  changeMode(mode: "SEND_AND_RECV" | "SIGNALLING_ONLY" | "RECV_ONLY"): void;

  /**
   * @description This method is used to leave the meeting for local participant
   */
  leave(): void;

  /**
   * @description This method is used to end the meeting for all participants
   */
  end(): void;

  /**
   * @param participantId `participantId` for which entry is to be responed
   * @param decision `true` if the participant is allowed to join the meeting else `false`
   */
  respondEntry(participantId: string, decision: boolean): void;
  /**
   * @description returns all the pinned participants in the meeting
   */
  get pinnedParticipants(): Map<string, Participant>;

  /**
   * @description Mute the mic of local participant and stop broadcasting audio
   */
  muteMic(): void;

  /**
   * @param customAudioTrack You can pass your own custom audio track here.
   * To learn more checkour this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/features/custom-track/custom-audio-track)
   * @description unmute the mic of local participant and start broadcasting audio
   */
  unmuteMic(customAudioTrack?: MediaStream): void;

  /**
   *
   * @description This method is used to stop boradcasting the video to other participants
   */
  disableWebcam(): void;

  /**
   * @param customVideoTrack You can pass your own custom video track here.
   * To learn more checkour this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/features/custom-track/custom-video-track)
   * @description This method will turn on the webcam of local participant and start broadcasting video
   */
  enableWebcam(customVideoTrack?: MediaStream): void;
  /**
   * @description This method is used to stop boradcasting the screenshare to other participants
   */
  disableScreenShare(): void;
  /**
   * @param customScreenSharingTrack You can pass your own custom screen share track here.
   * To learn more checkour this [reference](https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/features/custom-track/custom-screen-share-track)
   * @description This method will start broadcasting participants screen share
   *
   */
  enableScreenShare(customScreenSharingTrack?: MediaStream): void;

  /**
   * @deprecated
   * @param text Message which is to be send to all participants in th meeting
   */
  sendChatMessage(text: string): void;

  /**
   * @description This method is used to start the meeting transcription
   * @param config.webhookUrl? Webhook URL which will be called by VideoSDK when the transcription state gets changed
   * @param config.modelConfig? modelConfig if any, which will be used while doing transcription
   * @param config.summary.enabled Enables or disables summary generation from realtime transcriptions.
   * @param config.summary.prompt Guides summary generation (optional).
   */
  startTranscription({
    webhookUrl,
    modelConfig,
    summary,
  }: {
    webhookUrl?: string;
    modelConfig?: object;
    summary?: {
      enabled: boolean;
      prompt?: string;
    };
  }): void;

  /**
   * @description This method is used to stop the meeting transcription
   */
  stopTranscription(): void;

  /**
   * @param webhookUrl?
   *         Webhook URL which will be called by VideoSDK when the recording state gets changed
   * @param awsDirPath?
   *          awsDirPath represents the Directory you want to store your recording if you have configured your own S3 storage
   *
   * @param config Config can be used to configure the Recording
   * @param config.layout.type This represents the layout which is to used in the Recording
   * @param config.layout.priority This defines the priority of participants to be considered while composing Recording
   * @param config.layout.gridSize This defines the maximum number of participants in the grid
   * @param config.theme This defines the color theme of the Recording
   * @param config.mode This defines the mode of the Recording as only audio or vidoe and audio both
   * @param config.quality This defines the quality of the Recording
   *
   * @param transcription Configuration of post-meeting transcription and summary generation.
   * @param transcription.enabled Enables or disables post transcription.
   * @param transcription.summary.enabled Enables or disables summary generation from post transcriptions.
   * @param transcription.summary.prompt Guides summary generation (optional).
   */
  startRecording(
    webhookUrl: string,
    awsDirPath: string,
    config: {
      layout: {
        type: "GRID" | "SPOTLIGHT" | "SIDEBAR";
        priority: "SPEAKER" | "PIN";
        gridSize: number;
      };
      theme: "DARK" | "LIGHT" | "DEFAULT";
      mode: "video-and-audio" | "audio";
      quality: "low" | "med" | "high";
    },
    transcription?: {
      enabled: boolean;
      summary?: { enabled: boolean; prompt?: string };
    }
  ): void;

  /**
   * @description This method is used to stop the meeting recording
   */
  stopRecording(): void;

  /**
   * This method is used to start the meeting RTMP livestream to provided output
   * @param outputs This defines the array of outputs to which the RTMP livestream has to be broadcasted
   * @param config Config can be used to configure the RTMP livestream
   * @param config.layout.type This represents the layout which is to used in the RTMP livestream
   * @param config.layout.priority This defines the priority of participants to be considered while composing RTMP livestream
   * @param config.layout.gridSize This defines the maximum number of participants in the grid
   * @param config.theme This defines the color theme of the RTMP livestream
   *
   */
  startLivestream(
    outputs: Array<{
      url: string;
      streamKey: string;
    }>,
    config?: {
      layout: {
        type: "GRID" | "SPOTLIGHT" | "SIDEBAR";
        priority: "SPEAKER" | "PIN";
        gridSize: number;
      };
      theme: "DARK" | "LIGHT" | "DEFAULT";
    }
  ): void;

  /**
   * @description This method is used to stop the meeting livestream
   */
  stopLivestream(): void;

  /**
   * This method is used to start the meeting HLS
   * @param config Config can be used to configure the HLS stream
   * @param config.layout.type This represents the layout which is to used in the HLS
   * @param config.layout.priority This defines the priority of participants to be considered while composing HLS
   * @param config.layout.gridSize This defines the maximum number of participants in the grid
   * @param config.theme This defines the color theme of the HLS livestream
   * @param config.mode This defines the mode of the HLS livestream as only audio or vidoe and audio both
   * @param config.quality This defines the quality of the HLS livestream
   *
   * @param transcription Configuration of post-meeting transcription and summary generation.
   * @param transcription.enabled Enables or disables post transcription.
   * @param transcription.summary.enabled Enables or disables summary generation from post transcriptions.
   * @param transcription.summary.prompt Guides summary generation (optional).
   */
  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";
    },
    transcription?: {
      enabled: boolean;
      summary?: { enabled: boolean; prompt?: string };
    }
  ): Promise<void>;

  /**
   * @description This method is used to stop the meeting HLS
   */
  stopHls(): void;

  /**
   * @description This method is used to create the character participant
   * @param config.interactionId? id existing character interaction
   * @param config.id? id of character participant
   * @param config.characterMode? mode of character participant
   * @param config.characterRole? role of chracter participant
   * @param config.knowledgeBases? array of knowledgeBase id's
   */
  createCharacter(config: {
    interactionId?: string;
    // OR
    id?: string;
    displayName?: string;
    characterMode?: CharacterMode;
    characterRole?: string;
    knowledgeBases?: string[];
  }): Promise<Character>;
  /**
   * @description This method returns all the available mics
   */
  getMics(): Promise<
    Array<{
      deviceId: string;
      label: string;
    }>
  >;

  /**
   * @description This method returns all the available webcams
   */
  getWebcams(): Promise<
    Array<{
      deviceId: string;
      label: string;
      facingMode: "front" | "environment";
    }>
  >;

  /**
   * @description Enables Adaptive Subscription, which dynamically adjusts the subscribed video streams 
   * based on participant visibility and network conditions to optimize performance in large meetings.
   */
  enableAdaptiveSubscription(): void;

  /**
   * @description Disables Adaptive Subscription, forcing all subscribed video streams to remain active 
   * regardless of participant visibility or network conditions.
   */
  disableAdaptiveSubscription(): void;

  /**
   * @description Pause all the streams of the participants
   * @param kind This can be `audio`, `video`, `share_audio`, `share` or `all`
   */
  pauseAllStreams(kind?: "audio" | "video" | "share_audio" | "share" | "all"): void;

  /**
   * @description Resume all the streams of the participants
   * @param kind This can be `audio`, `video`, `share_audio`, `share` or `all`
   */
  resumeAllStreams(kind?: "audio" | "video" | "share_audio" | "share" | "all"): void;

  /**
   *
   * @param object This can be the  `deviceId` to which the mic input has to be changed or
   * you can pass the audio stream to this method which will be used for the audio broadcast
   */
  changeMic(object: string | MediaStream): void;

  /**
   *
   * @param object This can be the  `deviceId` to which the webcam input has to be changed or
   * you can pass the video stream to this method which will be used for the video broadcast
   */
  changeWebcam(object: string | MediaStream): void;

  /**
   * @param stream This method will be used to replace the provided stream with current webcam stream
   */
  replaceWebcamStream(stream: MediaStream): void;

  /**
   *
   * @param quality This method will be used set the webcam quality to be used.
   */
  setWebcamQuality(quality: "low" | "med" | "high"): void;

  /**
   * This method is used to start the whiteboard.
   */
  startWhiteboard: () => Promise<void>;

  /**
   * This method is used to stop the whiteboard.
   */
  stopWhiteboard: () => Promise<void>;

  /**
   * @deprecated
   * @param options
   */
  startVideo({ link }: { link: string }): void;
  /**
   * @deprecated
   */
  stopVideo(): void;
  /**
   * @deprecated
   */
  resumeVideo(): void;
  refreshConnection(): void;
  /**
   * @deprecated
   * @param options
   */
  pauseVideo({ currentTime }: { currentTime: number }): void;
  /**
   * @deprecated
   * @param options
   */
  seekVideo({ currentTime }: { currentTime: number }): void;
  /**
   *
   * @param {{base64Data: string, token: string, fileName: string}} options
   * @returns {Promise<string?>}
   */
  uploadBase64File: ({
    base64Data,
    token,
    fileName,
  }: {
    base64Data: string;
    token: string;
    fileName: string;
  }) => Promise<string | null>;
  /**
   *
   * @param {{url: string, token: string}} options
   * @returns {Promise<string?>}
   */
  fetchBase64File: ({
    url,
    token,
  }: {
    url: string;
    token: string;
  }) => Promise<string | null>;
  pubSub: {
    /**
     * Publish message to a topic
     *
     * @param topic Topic to which the message will be published
     * @param message This will be the actual message which has to be send
     * @param options This will define other options like `persist` which will decide if the message has to be stored or not
     */
    publish: (
      topic: string,
      message: string,
      options: {
        persist: boolean;
        sendOnly: Array<string>;
      }
    ) => Promise<void>;
    /**
     * Subscribe to message on a topic
     *
     * @param topic Topic to which you want to subscribe
     * @param callback Callback function which will be triggered when a new message is received
     */
    subscribe: (
      topic: string,
      callback: (message: {
        id: string;
        message: string;
        senderId: string;
        senderName: string;
        timestamp: string;
        topic: string;
        payload?: object;
      }) => void
    ) => Promise<
      Array<{
        id: string;
        message: string;
        senderId: string;
        senderName: string;
        timestamp: string;
        topic: string;
        payload?: object;
      }>
    >;
    /**
     * Unsubscribe from messages on a topic
     *
     * @param topic Topic to which you want to stop getting message for
     * @param callback Callback function which was passed which subscribing to the topic
     */
    unsubscribe: (
      topic: string,
      callback: (message: {
        id: string;
        message: string;
        senderId: string;
        senderName: string;
        timestamp: string;
        topic: string;
        payload?: object;
      }) => void
    ) => Promise<void>;
  };
  /**
   * @deprecated
   * @param options
   */
  connectTo({
    meetingId,
    payload,
  }: {
    meetingId: string;
    payload: string;
  }): Promise<void>;
  /**
   *
   * @returns {InputDeviceInfo}
   */
  get selectedCameraDevice(): InputDeviceInfo;
  /**
   *
   * @returns {InputDeviceInfo}
   */
  get selectedMicrophoneDevice(): InputDeviceInfo;
  /**
   * Add event listener
   * @param eventType Event name to which you want to subscribe.
   * @param listener Callback function which will be triggered when the event happens
   */
  on(
    eventType:
      | "participant-joined"
      | "participant-left"
      | "participant-mode-change"
      | "speaker-changed"
      | "presenter-changed"
      | "main-participant-changed"
      | "entry-requested"
      | "entry-responded"
      | "recording-started"
      | "recording-stopped"
      | "recording-state-changed"
      | "livestream-started"
      | "livestream-stopped"
      | "livestream-state-changed"
      | "hls-started"
      | "hls-stopped"
      | "hls-state-changed"
      | "stream-enabled"
      | "stream-disabled"
      | "whiteboard-started"
      | "whiteboard-stopped"
      | "meeting-joined"
      | "meeting-left"
      | "video-state-changed"
      | "video-seeked"
      | "mic-requested"
      | "webcam-requested"
      | "pin-state-changed"
      | "connection-open"
      | "connection-close"
      | "meeting-state-changed"
      | "switch-meeting"
      | "error"
      | "chat-message"
      | "transcription-state-changed"
      | "transcription-text"
      | "character-joined"
      | "character-left"
      | "paused-all-streams"
      | "resumed-all-streams",
    listener: (data: any) => void
  ): void;
  /**
   * Remove event listener
   * @param eventType Event name to which you want to unsubscribe.
   * @param listener Callback function which was passed while subscribing to the event
   */
  off(
    eventType:
      | "participant-joined"
      | "participant-left"
      | "participant-mode-change"
      | "speaker-changed"
      | "presenter-changed"
      | "main-participant-changed"
      | "entry-requested"
      | "entry-responded"
      | "recording-started"
      | "recording-state-changed"
      | "recording-stopped"
      | "livestream-started"
      | "livestream-stopped"
      | "livestream-state-changed"
      | "hls-started"
      | "hls-stopped"
      | "hls-state-changed"
      | "stream-enabled"
      | "stream-disabled"
      | "whiteboard-started"
      | "whiteboard-stopped"
      | "meeting-joined"
      | "meeting-left"
      | "video-state-changed"
      | "video-seeked"
      | "mic-requested"
      | "webcam-requested"
      | "pin-state-changed"
      | "connection-open"
      | "connection-close"
      | "meeting-state-changed"
      | "switch-meeting"
      | "error"
      | "chat-message"
      | "transcription-state-changed"
      | "transcription-text"
      | "character-joined"
      | "character-left"
      | "paused-all-streams"
      | "resumed-all-streams",

    listener: (data: any) => void
  ): void;
}

import { Participant } from "./participant";
import { Connection } from "./connection";
import { Character, CharacterMode } from "./character";
