import { Container, Module, ModuleDeclaration } from 'ditox';
import { Controller } from 'nrgy/mvc';
import { Observable } from 'rxjs';
import { Signal, Atom, Scope } from 'nrgy';
import { Query as Query$2 } from 'rx-effects';

type EventLike$1 = {
  type: string;
};

type KeyValueStorageEvent = {
  /**
   * The origin context of the event can be classified as 'local' when a storage
   * is modified by the current window or process, and as 'other' in all other cases.
   */
  readonly context: 'local' | 'other';
  /**
   * Returns a string with the key for the storage item that was changed.
   * The key attribute is null when the change is caused by the storage clear() method.
   */
  readonly key: string | null;
  /**
   * Returns a string with the new value of the storage item that was changed.
   * This value is null when the change has been invoked by storage clear() method,
   * or the storage item has been removed from the storage.
   */
  readonly newValue: string | null;
};
/**
 * This is a subset of  Web Storage API
 */
type KeyValueStorage = Readonly<{
  storageEvent: Observable<KeyValueStorageEvent>;
  /**
   * Returns the current value associated with the given key, or null if the
   * given key does not exist in the list associated with the object.
   */
  getItem: (key: string) => string | undefined;
  /**
   * Sets the value of the pair identified by key to value, creating a new
   * key/value pair if none existed for key previously.
   *
   * Throws a "QuotaExceededError" DOMException exception if the new value
   * couldn't be set. (Setting could fail if, e.g., the user has disabled
   * storage for the site, or if the quota has been exceeded.)
   */
  setItem: (key: string, value: string) => void;
  /**
   * Removes the key/value pair with the given key from the list associated
   * with the object, if a key/value pair with the given key exists.
   */
  removeItem: (key: string) => void;
  /**
   * Empties the list associated with the object of all key/value pairs, if
   * there are any.
   */
  clear: () => void;
  getKeys: () => ReadonlyArray<string>;
}>;

type AnyObject = Record<string, any>;
type Timestamp = number;
type UTCDate = string;

/** Autocomplete for string union with ability use any string
 * e.g. 'apple' | 'banana' | string
 *
 * WARNING: doesn't work as object key with empty default value
 * following code will throw type error:
 * const obj1: Record<Autocomplete<'foo' | 'bar'>, any> = {}
 */
type StringEnum<Enum extends string> = Enum | (string & Record<never, never>);

type ResultFailure<Error> = {
  readonly type: 'failure';
  readonly error: Error;
};
type ResultSuccess<Value> = {
  readonly type: 'success';
  readonly value: Value;
};
type SyncResult<Value, Error = unknown> =
  | ResultSuccess<Value>
  | ResultFailure<Error>;

type LogLevel = 'debug' | 'info' | 'warn' | 'error';
type LogMetadata = Readonly<Record<string, string>>;
type LogEvent = Readonly<{
  timestamp: number;
  level: LogLevel;
  tag: string;
  messages: ReadonlyArray<unknown>;
  meta?: LogMetadata;
}>;

type BaseRequestQuery = Record<
  string,
  string | boolean | number | (string | boolean | number)[]
>;
declare class HttpClientResponseError<
  ResponseError,
  RequestBody,
  RequestQuery extends BaseRequestQuery | void,
> extends Error {
  type: 'HttpClientResponseError';
  readonly request: HttpClientRequest<RequestBody, RequestQuery>;
  readonly status: number;
  readonly headers: Headers;
  readonly ok: false;
  readonly redirected: boolean;
  readonly statusText: string;
  readonly data: ResponseError;
  readonly originalResponse: Response;
  constructor(
    message: string,
    response: HttpClientResponseFailure<
      ResponseError,
      RequestBody,
      RequestQuery
    >,
    replaceResponseData?: ResponseError,
  );
}
declare class HttpClientFetchError<
  RequestBody = void,
  RequestQuery extends BaseRequestQuery | void = void,
> extends Error {
  type: 'HttpClientFetchError';
  readonly request: HttpClientRequest<RequestBody, RequestQuery>;
  constructor(
    message: string,
    response: HttpClientErrorResponse<RequestBody, RequestQuery>,
  );
}
type HttpClientRequest<
  RequestBody,
  RequestQuery extends BaseRequestQuery | void,
> = {
  body: RequestBody;
  url: string;
  method: string;
  credentials: string;
  mode: string;
  headers: HeadersInit;
  query: RequestQuery;
};
type HttpClientResponseFailure<
  ResponseError,
  RequestBody,
  RequestQuery extends BaseRequestQuery | void,
> = {
  originalResponse: Response;
  status: number;
  headers: Headers;
  redirected: boolean;
  statusText: string;
  request: HttpClientRequest<RequestBody, RequestQuery>;
  ok: false;
  data: ResponseError;
};
type HttpClientErrorResponse<
  RequestBody,
  RequestQuery extends BaseRequestQuery | void,
> = {
  request: HttpClientRequest<RequestBody, RequestQuery>;
};

type ApiAuthErrorResolution = 'retry' | 'fail';

type ConfigFlags<T extends Record<string, unknown>> = Readonly<T>;

type ReactionType = 'applause' | 'surprise' | 'smile' | 'like' | 'dislike';

/**
 * @deprecated use type Atom from nrgy
 * Provider of a state value.
 */
type Query$1<T> = Query$2<T>;
/**
 * Function which unsubscribes from something.
 */
type Unsubscriber$1 = () => void;
/**
 * @deprecated use watchAtom with option.skipFirst = false
 * Subscribes a listener on a value of the query and its changes.
 * @example
 * ```ts
import {
  handleQuery,
} from '@salutejs/jazz-sdk-web';

...

const unsubscribe = handleQuery(room.participants, (participants) => {
  console.log(participants);
});

unsubscribe()
```
 */
declare function handleQuery<T>(
  query: Query$1<T> | Atom<T>,
  observer: (value: T) => unknown,
): Unsubscriber$1;
/**
 * Subscribes a listener on changes of the query only.
 * @deprecated use watchAtom
 * @example
 * ```ts
import {
  handleQueryChanges,
} from '@salutejs/jazz-sdk-web';

...

const unsubscribe = handleQueryChanges(room.participants, (participants) => {
  console.log(participants);
});

unsubscribe()
```

 */
declare function handleQueryChanges<T>(
  query: Query$1<T> | Atom<T>,
  listener: (value: T) => unknown,
): Unsubscriber$1;
/**
 * Subscribes to changes of the given atom and notifies the listener on new values.
 *
 * @template T - The type of the values emitted by the atom .
 * @param atom - An Atom to observe.
 * @param listener - A callback function invoked with the current or updated value.
 * @param options - Optional configuration:
 *   - sync: (not currently used) potential flag to control synchronous behavior.
 *   - onlyChanges: (not currently used) potential flag to notify only on changed values.
 *   - skipFirst: Whether to skip the first emitted value (default: true).
 *
 * @returns A function to unsubscribe from the observed value changes.
 *
 * This function works by subscribing to the observable stream representing the atom.
 * If skipFirst is true, it discards the initial value emission; otherwise, it includes it.
 * This allows flexible control over initial notification behavior during subscription.
 *
 * @example
 * ```ts
import {
  watchAtom,
} from '@salutejs/jazz-sdk-web';

...
const participants = room.participants()
const unsubscribe = watchAtom(room.participants, (_participants) => {
  participants = _participants
});

unsubscribe()
```
 */
declare function watchAtom<T>(
  atom: Atom<T> | Query$1<T>,
  listener: (value: T) => unknown,
  options?: {
    sync?: boolean | undefined;
  },
): Unsubscriber$1;
/**
 * Subscribes a listener on an event bus by type.
 *
 * @example
 * ```ts
import {
  handleEvent,
} from '@salutejs/jazz-sdk-web';

...

const unsubscribe = handleEvent(
  client.event$,
  'addRoom',
  async ({ payload }) => {
    console.log(payload.room);
  },
);

unsubscribe();
```
 */
declare function handleEvent<
  Event extends EventLike$1,
  Type extends Event['type'],
  TypedEvent extends Event & {
    type: Type;
  },
>(
  eventBus: Observable<Event> | Signal<Event>,
  type: Type,
  listener: (event: TypedEvent) => unknown,
  isOnce?: boolean,
): Unsubscriber$1;
/**
 * Subscribes a listener on an event bus.
 *
 * @example
 * ```ts
import {
  handleEvents,
} from '@salutejs/jazz-sdk-web';

...

const unsubscribe = handleEvents(client.event$, (event) => {
  if (event.type === 'addRoom') {
    console.log(payload.room);
  }
});

unsubscribe()
```
 */
declare function handleEvents<Event extends EventLike$1>(
  eventBus: Observable<Event> | Signal<Event>,
  listener: (event: Event) => unknown,
  isOnce?: boolean,
): Unsubscriber$1;

type PayloadError<Code, Params> = {
  code: Code;
  reason?: Code;
  message?: string;
  params?: Params;
};

type RequestId = string;
type EventOk<T = string, P = unknown> = {
  event: T;
  requestId: RequestId;
  roomId: string;
  groupId: string | undefined;
  payload: P;
};
type EventError<
  Code = string,
  Params = unknown,
  Error extends string = 'error',
> = {
  event: Error;
  requestId: RequestId;
  roomId: string;
  groupId: string | undefined;
  payload: PayloadError<Code, Params>;
};

/**
 * Event name for subscribe to all events in transport
 */
declare type AllEventTypes = '*';

declare type AllNodeTypes =
  | TransportRoot<any>
  | BaseTransportNode
  | BaseTransportNodeReadonly;

declare interface BaseEventBusReadonly<EVENTS extends EventLike>
  extends BaseEventBusSubscriber<EVENTS> {
  name?: string;
}

declare interface BaseEventBusSubscriber<EVENTS extends EventLike> {
  /**
   * Method for subscribing to bus events.
   * In addition to events of the type, you can also specify the * event,
   * which will allow you to subscribe to all bus events.
   * The method returns a function for unsubscribing the callback
   * (this can also be done via the off or removeEventListener methods).
   *
   * If the onSubscribe lifecycle method is passed,
   * it will be called when this event is sent.
   *
   * If the transport was destroyed, this method will do nothing.
   *
   * @example
   * ```ts
   * type Events = { event: string };
   * const eventBus = createBaseEventBus<Events>();
   *
   * const unsubscriber = eventBus.on('event', (event, payload) => console.log(payload));
   * unsubscriber();
   *
   * eventBus.send('event', 'test');
   * ```
   */
  on<EVENT extends string & keyof EVENTS>(
    event: EVENT,
    callback: (event: EVENT, payload: EVENTS[EVENT]) => void,
  ): Unsubscriber;
  /**
   * unsubscribe from an event.
   * If there are no subscribers left for the event, we remove it from the map.
   *
   * If the onUnsubscribe lifecycle callback is passed,
   * it will be called each time this function is called.
   *
   * If the transport was destroyed, the method does not work.
   *
   * @example
   * ```ts
   * type Events = { event: string };
   * const eventBus = createBaseEventBus<Events>();
   *
   * function handler(type: string, payload: string): void {}
   *
   * eventBus.on('event', handler);
   * eventBus.off('event', handler);
   * ```
   */
  off<EVENT extends string & keyof EVENTS>(
    event: EVENT,
    callback: (event: EVENT, payload: EVENTS[EVENT]) => void,
  ): void;
}

declare interface BaseTransportNode extends DestroyedNode {
  name?: string;
  __isRoot: Readonly<false>;
  /**
   * Method to get the root node object referenced by the node.
   */
  getTransports: () => TransportRootNodes;
}

declare interface BaseTransportNodeReadonly {
  name?: string;
  __isRoot: Readonly<false>;
  /**
   * A property indicating that a class has been destroyed.
   * Once resolved, all methods in it stop working and the data is cleared.
   */
  isDestroyed: boolean;
  /**
   * Method to get the root node object referenced by the node.
   */
  getTransports: () => TransportRootNodes;
}

declare interface BaseTransportRoot extends DestroyedNode {
  name?: string;
  __isRoot: Readonly<true>;
}

/**
 * A node that has a cleanup mechanism. After the method chchchch is executed,
 * the node becomes inactive because event subscriptions and message sending stop functioning.
 */
declare interface DestroyedNode {
  /**
   * whether the transport is destroyed.
   * If the transport is destroyed,
   * then subscriptions and event sending do not work, and the subscriber list is destroyed.
   * Also, all dependent nodes are automatically unsubscribed from the destroyed node.
   */
  isDestroyed: boolean;
  destroy(): void;
}

declare type EventLike = Record<string, unknown>;

declare type Namespace = string;

declare interface SubscribeNode<EVENTS extends EventLike>
  extends TransportNodeBase<EVENTS> {
  add<
    TYPES extends string & keyof EVENTS,
    TYPE extends Type,
    ALL_NAMESPACES extends UtilsTypeFilterTypesWithNamespaces<TYPES, TYPE>,
  >(
    namespace: ALL_NAMESPACES | '',
    root: AllNodeTypes,
  ): void;
  remove<
    TYPES extends string & keyof EVENTS,
    TYPE extends Type,
    ALL_NAMESPACES extends UtilsTypeFilterTypesWithNamespaces<TYPES, TYPE>,
  >(
    namespace: ALL_NAMESPACES | '',
    root: AllNodeTypes,
  ): void;
  channel<
    EVENT_TYPES extends string & keyof EVENTS,
    TYPES extends string,
    CHANNEL extends UtilsTypeFilterTypesWithNamespaces<EVENT_TYPES, TYPES>,
    CHANNEL_EVENTS_TYPES extends UtilsTypeRemoveNamespaceFromType<
      EVENT_TYPES,
      CHANNEL
    >,
    CHANNEL_EVENTS extends {
      [TYPE in CHANNEL_EVENTS_TYPES]: EVENTS[`${CHANNEL}:${TYPE}`];
    },
  >(
    channel: CHANNEL,
  ): SubscribeNode<CHANNEL_EVENTS>;
  asReadonly(): SubscribeReadonlyNode<EVENTS>;
}

declare interface SubscribeNodeSubscribers<EVENTS extends EventLike> {
  on<
    EVENTS_KEYS extends keyof EVENTS,
    TYPE extends string,
    NAMESPACES extends UtilsTypeFilterTypesWithNamespaces<
      string & EVENTS_KEYS,
      TYPE
    >,
    EVENT_TYPE extends
      | `${NAMESPACES}:${AllEventTypes}`
      | AllEventTypes
      | (string & EVENTS_KEYS),
    NEW_NAMESPACE extends UtilsTypeFilterTypesWithNamespaces<EVENT_TYPE, TYPE>,
    CALLBACK_EVENTS extends EVENT_TYPE extends AllEventTypes
      ? string & EVENTS_KEYS
      : EVENT_TYPE extends `${NAMESPACES}:${AllEventTypes}`
        ? UtilsTypeRemoveNamespaceFromType<string & EVENTS_KEYS, NEW_NAMESPACE>
        : EVENT_TYPE,
    CALLBACK_PARAMS extends {
      [TYPE in CALLBACK_EVENTS]: [event: TYPE, payload: EVENTS[TYPE]];
    },
  >(
    event: EVENT_TYPE,
    callback: (...args: CALLBACK_PARAMS[CALLBACK_EVENTS]) => void,
  ): Unsubscriber;
  once<
    EVENTS_KEYS extends keyof EVENTS,
    TYPE extends string,
    NAMESPACES extends UtilsTypeFilterTypesWithNamespaces<
      string & EVENTS_KEYS,
      TYPE
    >,
    EVENT_TYPE extends
      | `${NAMESPACES}:${AllEventTypes}`
      | AllEventTypes
      | (string & EVENTS_KEYS),
    NEW_NAMESPACE extends UtilsTypeFilterTypesWithNamespaces<EVENT_TYPE, TYPE>,
    CALLBACK_EVENTS extends EVENT_TYPE extends AllEventTypes
      ? string & EVENTS_KEYS
      : EVENT_TYPE extends `${NAMESPACES}:${AllEventTypes}`
        ? UtilsTypeRemoveNamespaceFromType<string & EVENTS_KEYS, NEW_NAMESPACE>
        : EVENT_TYPE,
    CALLBACK_PARAMS extends {
      [TYPE in CALLBACK_EVENTS]: [event: TYPE, payload: EVENTS[TYPE]];
    },
  >(
    event: EVENT_TYPE,
    callback: (...args: CALLBACK_PARAMS[CALLBACK_EVENTS]) => void,
  ): Unsubscriber;
  off<
    EVENTS_KEYS extends keyof EVENTS,
    TYPE extends string,
    NAMESPACES extends UtilsTypeFilterTypesWithNamespaces<
      string & EVENTS_KEYS,
      TYPE
    >,
    EVENT_TYPE extends
      | `${NAMESPACES}:${AllEventTypes}`
      | AllEventTypes
      | (string & EVENTS_KEYS),
  >(
    type: EVENT_TYPE,
    callback: (...args: any[]) => void,
  ): void;
}

declare interface SubscribeReadonlyNode<EVENTS extends EventLike>
  extends SubscribeReadonlyNodeExtends<EVENTS> {}

declare type SubscribeReadonlyNodeExtends<EVENTS extends EventLike> =
  BaseTransportNodeReadonly & SubscribeNodeSubscribers<EVENTS>;

declare type TransportLifecycleEvents<EVENTS extends EventLike> = {
  /**
   * The transport was cleared. After that,
   * it stops functioning and all data in it is cleared.
   */
  destroy: undefined;
  /**
   * Subscribed to some event.
   * The object indicates what event was subscribed to and whether it is the first.
   */
  subscribe: {
    event: string & keyof EVENTS;
    mode: 'on' | 'once';
    subscriber: Parameters<TransportRootSubscribers<EVENTS>['on']>[1];
    subscribersCount: number;
  };
  /**
   * Unsubscribed from some event.
   * The object indicates what event was unsubscribed from and whether there are more subscribers.
   */
  unsubscribe: {
    event: string & keyof EVENTS;
    mode: 'on' | 'once';
    subscriber: Parameters<TransportRootSubscribers<EVENTS>['off']>[1];
    subscribersCount: number;
  };
};

declare type TransportNodeBase<EVENTS extends EventLike> =
  SubscribeNodeSubscribers<EVENTS> & BaseTransportNode;

declare interface TransportReadonlyNode<EVENTS extends EventLike>
  extends TransportReadonlyNodeBase<EVENTS> {
  lifecycle: TransportRoot<EVENTS>['lifecycle'];
}

declare type TransportReadonlyNodeBase<EVENTS extends EventLike> =
  TransportRootSubscribers<EVENTS> & BaseTransportNodeReadonly;

declare interface TransportRoot<EVENTS extends EventLike>
  extends TransportRootBase<EVENTS> {
  /**
   * Sync mode sending events
   *
   * @default false
   */
  sync?: Readonly<boolean>;
  /**
   * Method for sending an event to listeners.
   * If the transport was destroyed,
   * or no one is subscribed to this event, the method will do nothing.
   *
   * If there are subscribers to *,
   * they will listen to all events that were forwarded.
   *
   * The method works in 2 modes: synchronous and asynchronous (asynchronous mode is enabled by default).
   * To change this, you need to pass the 3rd argument.
   *
   * @example
   * ```ts
   * type Events = { event: string, event_empty: undefined };
   * const transport = createTransport<Events>();
   *
   * transport.on('event', (event, payload) => console.log(payload));
   * transport.on('event_empty', (event, payload) => console.log(payload));
   * transport.on('*', (event, payload) => console.log(payload));
   *
   * transport.send('event', 'test');
   * transport.send('event_empty');
   * transport.send('event_empty', undefined);
   * ```
   */
  send<
    TYPE extends string & keyof EVENTS,
    PARAMETERS extends EVENTS[TYPE] extends undefined
      ? (payload?: EVENTS[TYPE]) => void
      : (payload: EVENTS[TYPE]) => void,
  >(
    type: TYPE,
    ...other: Parameters<PARAMETERS>
  ): void;
  /**
   * Method for getting a node that has only subscription interfaces (on/once/off).
   * Recommended for use in public API services to hide methods
   * for direct control of transport state from the outside.
   */
  asReadonly(): TransportReadonlyNode<EVENTS>;
}

declare type TransportRootBase<EVENTS extends EventLike> =
  TransportRootSubscribers<EVENTS> &
    BaseTransportRoot & {
      /**
       * Transport lifecycle event bus. You can subscribe to 3 events:
       * 1) destroy - the transport was cleared. After that, it stops functioning and all data in it is cleared.
       * 2) subscribe - subscribed to some event. The object indicates what event was subscribed to and whether it is the first.
       * 3) unsubscribe - unsubscribed from some event. The object indicates what event was unsubscribed from and whether there are more subscribers.
       *
       * When the main transport is destroyed, the lifecycle event bus also dies.
       *
       * @example
       * ```ts
       * const transport = createTransport<Events>();
       *
       * transport.lifecycle.on('destroy', () => console.log('transport is destroy'));
       * transport.lifecycle.on('subscribe', ({ event, isFirstSubscribe }) => console.log(`subscribe to event ${event} isFirst=${isFirstSubscribe}`));
       * transport.lifecycle.on('unubscribe', ({ event, isHasSubscribers }) => console.log(`unsubscribe from event ${event} isHasSubscribers=${isHasSubscribers}`));
       *
       * const unsubscriber1 = transport.on('event1', () => {}) // subscribe to event event1 isFirst=true
       * const unsubscriber2 = transport.on('event1', () => {}) // subscribe to event event1 isFirst=false
       * const unsubscriber3 = transport.on('event2', () => {}) // subscribe to event event2 isFirst=true
       *
       * unsubscriber3() // unsubscribe from event event2 isHasSubscribers=false
       * unsubscriber2() // unsubscribe from event event1 isHasSubscribers=true
       * unsubscriber1() // unsubscribe from event event1 isHasSubscribers=false
       *
       * transport.destroy(); // transport is destroy
       * ```
       */
      lifecycle: Readonly<
        BaseEventBusReadonly<TransportLifecycleEvents<EVENTS>>
      >;
    };

/**
 * List of nodes the node is subscribed to.
 */
declare type TransportRootNodes = Record<Namespace, Array<TransportRoot<any>>>;

declare interface TransportRootSubscribers<EVENTS extends EventLike> {
  /**
   * Method for subscribing to bus events.
   * In addition to events of the type, you can also specify the * event,
   * which will allow you to subscribe to all bus events.
   * The method returns a function for unsubscribing the callback
   * (this can also be done via the off or removeEventListener methods).
   *
   * If the onSubscribe lifecycle method is passed,
   * it will be called when this event is sent.
   *
   * If the transport was destroyed, this method will do nothing.
   *
   * @example
   * ```ts
   * type Events = { event: string };
   * const transport = createTransport<Events>();
   *
   * transport.on('event', (event, payload) => console.log(payload));
   * const unsubscriber = transport.on('*', (event, payload) => console.log(payload));
   * unsubscriber();
   *
   * transport.send('event', 'test');
   * ```
   */
  on<
    EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes),
    EVENT extends EVENT_TYPE extends AllEventTypes
      ? string & keyof EVENTS
      : EVENT_TYPE,
    CB extends {
      [TYPE in EVENT]: [TYPE, EVENTS[TYPE]];
    },
  >(
    event: EVENT_TYPE,
    callback: (...args: CB[EVENT]) => void,
  ): Unsubscriber;
  /**
   * A method for one-time subscription to bus events.
   * In addition to events of the type, you can also specify an event *,
   * which will allow you to subscribe to all bus events.
   * The method returns a function for unsubscribing the callback
   * (this can also be done via the off or removeEventListener methods).
   *
   * If the onSubscribe lifecycle method is passed,
   * it will be called when this event is sent.
   *
   * If the transport was destroyed, this method will do nothing.
   *
   * @example
   * ```ts
   * type Events = { event: string };
   * const transport = createTransport<Events>();
   *
   * transport.once('event', (event, payload) => console.log(payload));
   * const unsubscriber = transport.once('*', (event, payload) => console.log(payload));
   * unsubscriber();
   *
   * transport.send('event', 'test');
   * transport.send('event', 'test'); // not call subscribers
   * ```
   */
  once<
    EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes),
    EVENT extends EVENT_TYPE extends AllEventTypes
      ? string & keyof EVENTS
      : EVENT_TYPE,
    CB extends {
      [TYPE in EVENT]: [TYPE, EVENTS[TYPE]];
    },
  >(
    event: EVENT_TYPE,
    callback: (...args: CB[EVENT]) => void,
  ): Unsubscriber;
  /**
   * unsubscribe from an event.
   * If there are no subscribers left for the event, we remove it from the map.
   *
   * If the onUnsubscribe lifecycle callback is passed,
   * it will be called each time this function is called.
   *
   * If the transport was destroyed, the method does not work.
   *
   * @example
   * ```ts
   * type Events = { event: string };
   * const transport = createTransport<Events>();
   *
   * function handler(type: string, payload: string): void {}
   *
   * transport.on('event', handler);
   * transport.off('event', handler);
   * ```
   */
  off<EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes)>(
    event: EVENT_TYPE,
    callback: (...args: any[]) => void,
  ): void;
}

declare type Type = string;

/**
 * unsubscribe function to unsubscribe from an event.
 */
declare type Unsubscriber = () => void;

/**
 * Utility type for adding to namespace event names
 *
 * @example
 *
 * type Event = { event1: boolean; event2: number; }
 * UtilsTypeAddNamespaceToEvents<'namespace', Event> // { 'namespace:event1': boolean; 'namespace:event2': number; }
 */
declare type UtilsTypeAddNamespaceToEvents<
  NAMESPACE extends string,
  EVENT extends EventLike,
> = NAMESPACE extends ''
  ? EVENT
  : {
      [TYPE in UtilsTypeAddNamespaceToType<
        NAMESPACE,
        string & keyof EVENT
      >]: EVENT[UtilsTypeRemoveNamespaceFromType<TYPE, NAMESPACE>];
    };

/**
 * Utility type for gluing namespace and type name
 *
 * @example
 * UtilsTypeAddNamespaceToType<'namespace', 'type'> // 'namespace:type'
 */
declare type UtilsTypeAddNamespaceToType<
  NAMESPACE extends string,
  TYPE extends string,
> = `${NAMESPACE}:${TYPE}`;

/**
 * Utility type for getting namespace from event name (max size 5 namespaces)
 *
 * @example
 *
 * UtilsTypeFilterTypesWithNamespaces<'namespace1:event', 'event'> // 'namespace1'
 * UtilsTypeFilterTypesWithNamespaces<'namespace1:namespace2:event', 'event'> // 'namespace1:namespace2'
 * UtilsTypeFilterTypesWithNamespaces<'namespace1:namespace2:namespace3:event', 'event'> // 'namespace1:namespace2:namespace3'
 */
declare type UtilsTypeFilterTypesWithNamespaces<
  STR extends string,
  TYPE extends string,
> = STR extends `${infer NAMESPACE_1}:${infer NAMESPACE_2}:${infer NAMESPACE_3}:${infer NAMESPACE_4}:${infer NAMESPACE_5}:${TYPE}`
  ? `${NAMESPACE_1}:${NAMESPACE_2}:${NAMESPACE_3}:${NAMESPACE_4}:${NAMESPACE_5}`
  : STR extends `${infer NAMESPACE_1}:${infer NAMESPACE_2}:${infer NAMESPACE_3}:${infer NAMESPACE_4}:${TYPE}`
    ? `${NAMESPACE_1}:${NAMESPACE_2}:${NAMESPACE_3}:${NAMESPACE_4}`
    : STR extends `${infer NAMESPACE_1}:${infer NAMESPACE_2}:${infer NAMESPACE_3}:${TYPE}`
      ? `${NAMESPACE_1}:${NAMESPACE_2}:${NAMESPACE_3}`
      : STR extends `${infer NAMESPACE_1}:${infer NAMESPACE_2}:${TYPE}`
        ? `${NAMESPACE_1}:${NAMESPACE_2}`
        : STR extends `${infer NAMESPACE}:${TYPE}`
          ? `${NAMESPACE}`
          : never;

/**
 * Utility type of extraction from event name type without namespace
 *
 * @example
 * UtilsTypeRemoveNamespaceFromType<'namespace:event', 'namespace'> // 'event'
 */
declare type UtilsTypeRemoveNamespaceFromType<
  NAMESPACED_TYPE extends string,
  NAMESPACE extends string,
> = NAMESPACED_TYPE extends `${NAMESPACE}:${infer TYPE}` ? TYPE : never;

type JitsiXmppEvents = {
  /**
   * Indicates error while adding ice candidate.
   */
  'xmpp.add_ice_candidate_failed': [];

  // Designates an event indicating that the focus has asked us to mute our
  // audio.
  'xmpp.audio_muted_by_focus': [];

  // Designates an event indicating that the focus has asked us to disable our
  // camera.
  'xmpp.video_muted_by_focus': [];
  'xmpp.authentication_required': [];
  'xmpp.bridge_down': [];

  /**
   * Triggered when 'session-accept' is received from the responder.
   */
  'xmpp.callaccepted.jingle': [];

  // Designates an event indicating that an offer (e.g. Jingle
  // session-initiate) was received.
  'xmpp.callincoming.jingle': [];

  // Triggered when Jicofo kills our media session, this can happen while
  // we're still in the MUC, when it decides to terminate the media session.
  // For example when the session is idle for too long, because we're the only
  // person in the conference room.
  'xmpp.callended.jingle': [];
  'xmpp.chat_error_received': [];

  // The conference properties (as advertised by jicofo) have changed
  'xmpp.conference_properties_changed': [];

  /**
   * This event is triggered when the ICE connects for the first time.
   */
  'xmpp.connection.connected': [];

  // Designates an event indicating that the connection to the XMPP server
  // failed.
  'xmpp.connection.failed': [];

  // Designates an event indicating that the media (ICE) connection was
  // interrupted. This should go to the RTC module.
  'xmpp.connection.interrupted': [];

  // Designates an event indicating that the media (ICE) connection was
  // restored. This should go to the RTC module.
  'xmpp.connection.restored': [];

  // Designates an event indicating that the media (ICE) connection failed.
  // This should go to the RTC module.
  'xmpp.connection.ice.failed': [];

  // Designates an event indicating that the call has been migrated to a different
  // bridge and that the client needs to be restarted for a successful transition.
  'xmpp.connection.restart': [];

  /**
   * Designates an event indicating connection status changes.
   */
  'xmpp.connection.status.changed': [];

  // Designates an event indicating that the display name of a participant
  // has changed.
  'xmpp.display_name_changed': [];

  /**
   * Chat room instance have been added to Strophe.emuc plugin.
   */
  'xmpp.emuc_room_added': [];

  /**
   * Chat room instance have been removed from Strophe.emuc plugin.
   */
  'xmpp.emuc_room_removed': [];
  'xmpp.etherpad': [];
  'xmpp.focus_disconnected': [];
  'xmpp.focus_left': [];
  'xmpp.graceful_shutdown': [];

  /**
   * Event fired when 'transport-replace' Jingle message has been received,
   * before the new offer is set on the PeerConnection.
   */
  'rtc.ice_restarting': [];

  /**
   * Event fired after the 'transport-replace' message has been processed
   * and the new offer has been set successfully.
   */
  'rtc.ice_restart_success': [];

  /**
   * Designates an event indicating that we were kicked from the XMPP MUC.
   * @param {boolean} isSelfPresence - whether it is for local participant
   * or another participant.
   * @param {string} actorJid - the jid of the participant who was initator
   * of the kick.
   * @param {?string} participantJid - when it is not a kick for local participant,
   * this is the jid of the participant which was kicked.
   */
  'xmpp.kicked': [];

  // Designates an event indicating that our role in the XMPP MUC has changed.
  'xmpp.localrole_changed': [];

  /**
   * Event fired when the unique meeting id is set.
   */
  'xmpp.meeting_id_set': [];

  // Designates an event indicating that an XMPP message in the MUC was
  // received.
  'xmpp.message_received': [];

  // Designates an event indicating that an invite XMPP message in the MUC was
  // received.
  'xmpp.invite_message_received': [
    roomJid: string,
    from: string,
    txt: string,
    invitePassword: string,
  ];

  // Designates an event indicating that a private XMPP message in the MUC was
  // received.
  'xmpp.private_message_received': [];

  // Designates an event indicating that a bot participant type had changed
  'xmpp.muc_member_bot_type_changed': [];

  // Designates an event indicating that the XMPP MUC was destroyed.
  'xmpp.muc_destroyed': [];

  // Designates an event indicating that we have joined the XMPP MUC.
  'xmpp.muc_joined': [];

  // Designates an event indicating that a participant joined the XMPP MUC.
  'xmpp.muc_member_joined': [];

  // Designates an event indicating that a participant left the XMPP MUC.
  'xmpp.muc_member_left': [];

  // Designates an event indicating that a participant joined the lobby XMPP MUC.
  'xmpp.muc_lobby_member_joined': [];

  // Designates an event indicating that a participant in the lobby XMPP MUC has been updated
  'xmpp.muc_lobby_member_updated': [];

  // Designates an event indicating that a participant left the XMPP MUC.
  'xmpp.muc_lobby_member_left': [];

  // Designates an event indicating that a participant was denied access to a conference from the lobby XMPP MUC.
  'xmpp.muc_denied access': [];

  // Designates an event indicating that local participant left the muc
  'xmpp.muc_left': [];

  // Designates an event indicating that the MUC role of a participant has
  // changed.
  'xmpp.muc_role_changed': [];

  // Designates an event indicating that the MUC has been locked or unlocked.
  'xmpp.muc_lock_changed': [];

  // Designates an event indicating that the MUC members only config has changed.
  'xmpp.muc_members_only_changed': [];

  // Designates an event indicating that a participant in the XMPP MUC has
  // advertised that they have audio muted (or unmuted).
  'xmpp.audio_muted': [];

  // Designates an event indicating that a participant in the XMPP MUC has
  // advertised that they have video muted (or unmuted).
  'xmpp.video_muted': [];

  // Designates an event indicating that the video type (e.g. 'camera' or
  // 'screen') for a participant has changed.
  // Note: currently this event fires every time we receive presence from
  // someone (regardless of whether or not the "video type" changed).
  'xmpp.video_type': [];

  /**
   * Indicates that the features of the participant has been changed.
   */
  'xmpp.participant_features_changed': [];
  'xmpp.password_required': [];

  /**
   * Indicates that phone number changed.
   */
  'conference.phoneNumberChanged': [];
  'xmpp.presence_received': [];
  'xmpp.presence_status': [];
  'xmpp.prompt_for_login': [];

  // xmpp is connected and obtained user media
  'xmpp.ready_to_join': [];

  /**
   * Indicates that recording state changed.
   */
  'xmpp.recorderStateChanged': [];

  // Designates an event indicating that we received statistics from a
  // participant in the MUC.
  'xmpp.remote_stats': [];

  /**
   * Indicates that the offer / answer renegotiation has failed.
   */
  'xmpp.renegotiation_failed': [];
  'xmpp.room_reservation_error': [];
  'xmpp.room_connect_error': [];
  'xmpp.room_connect_error.not_allowed': [];
  'xmpp.room_join_error': [];
  'xmpp.room_connect_error.members_only': [];

  /**
   * Indicates that max users limit has been reached.
   */
  'xmpp.room_max_users_error': [];

  // Designates an event indicating that we sent an XMPP message to the MUC.
  'xmpp.sending_chat_message': [];

  // Designates an event indicating that we sent a private XMPP message to
  // a specific user of the muc.
  'xmpp.sending_private_chat_message': [];

  // Event fired after receiving the confirmation about session accept.
  'xmpp.session_accept': [];

  // Event fired if we receive an error after sending the session accept.
  'xmpp.session_accept_error': [];

  /**
   * Event fired when we do not get our 'session-accept' acknowledged by
   * Jicofo. It most likely means that there is serious problem with our
   * connection or XMPP server and we should reload the conference.
   *
   * We have seen that to happen in BOSH requests race condition when the BOSH
   * request table containing the 'session-accept' was discarded by Prosody.
   * Jicofo does send the RESULT immediately without any condition, so missing
   * packets means that most likely it has never seen our IQ.
   */
  'xmpp.session_accept_timeout': [];

  /**
   * Event fired when speaker stats update message is received.
   */
  'xmpp.speaker_stats_received': [];

  /**
   * Event fired when conference creation timestamp is received.
   */
  'xmpp.conference_timestamp_received': [];

  /**
   * Event fired when we receive a message for AV moderation approved for the local participant.
   */
  'xmpp.av_moderation.approved': [];

  /**
   * Event fired when we receive a message for AV moderation.
   */
  'xmpp.av_moderation.received': [];

  /**
   * Event fired when the moderation enable/disable changes.
   */
  'xmpp.av_moderation.changed': [];

  /**
   * Event fired when we receive message that a new jid was approved.
   */
  'xmpp.av_moderation.participant.approved': [];

  // Designates an event indicating that we should join the conference with
  // audio and/or video muted.
  'xmpp.start_muted_from_focus': [];

  // Designates an event indicating that the subject of the XMPP MUC has
  // changed.
  'xmpp.subject_changed': [];

  // FIXME: how does it belong to XMPP ? - it's detected by the PeerConnection
  // suspending detected
  'xmpp.suspend_detected': [];

  /**
   * Notifies for transcription status changes. The event provides the
   * following parameters to its listeners:
   *
   * @param {String} status - The new status.
   */
  'xmpp.transcription_status_changed': [];

  /**
   * Event fired when 'transport-info' with new ICE candidates is received.
   */
  'xmpp.transportinfo.jingle': [];

  /**
   * Indicates that video SIP GW state changed.
   *
   * @param {VideoSIPGWConstants} status - Any of the following statuses:
   * STATUS_BUSY, STATUS_AVAILABLE or STATUS_UNDEFINED.
   */
  'xmpp.videoSIPGWAvailabilityChanged': [];

  /**
   * Indicates that video SIP GW Session state changed.
   * The statuses are any of the following statuses:
   * STATE_ON, STATE_OFF, STATE_PENDING, STATE_RETRYING, STATE_FAILED.
   * {@see VideoSIPGWConstants}
   *
   * @param {options} event - {address, oldState, newState, displayName}.
   */
  'xmpp.videoSIPGWSessionStateChanged': [];

  // Designates an event indicating that the local ICE connection state has
  // changed.
  'xmpp.ice_connection_state_changed': [];

  /**
   * Event which is emitted when the body in an XMPP message in the MUC
   * contains JSON
   */
  'xmmp.json_message_received': [from: string, data: unknown];
};

type JitsiXmppEventType$1 = keyof JitsiXmppEvents;

type JitsiRTCEventType$1 =
  /**
   * Indicates error while create answer call.
   */
  | 'rtc.create_answer_failed'
  /**
   * Indicates error while create offer call.
   */
  | 'rtc.create_offer_failed'
  | 'rtc.data_channel_open'
  | 'rtc.endpoint_conn_status_changed'
  | 'rtc.dominant_speaker_changed'
  | 'rtc.lastn_endpoint_changed'
  /**
   * Event emitted when the user granted/blocked a permission for the camera / mic.
   * Used to keep track of the granted permissions on browsers which don't
   * support the Permissions API.
   */
  | 'rtc.permissions_changed'
  | 'rtc.sender_video_constraints_changed'
  /**
   * Event emitted when {@link RTC.setLastN} method is called to update with
   * the new value set.
   * The first argument is the value passed to {@link RTC.setLastN}.
   */
  | 'rtc.lastn_value_changed'
  /**
   * Event emitted when ssrc for a local track is extracted and stored
   * in {@link TraceablePeerConnection}.
   * @param {JitsiLocalTrack} track which ssrc was updated
   * @param {string} ssrc that was stored
   */
  | 'rtc.local_track_ssrc_updated'
  /**
   * The max enabled resolution of a local video track was changed.
   */
  | 'rtc.local_track_max_enabled_resolution_changed'
  | 'rtc.track_attached'
  /**
   * Event fired when we remote track is added to the conference.
   * 1st event argument is the added <tt>JitsiRemoteTrack</tt> instance.
   **/
  | 'rtc.remote_track_added'
  // FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event
  // (currently implemented for local tracks only)
  | 'rtc.remote_track_mute'
  /**
   * Indicates that the remote track has been removed from the conference.
   * 1st event argument is the removed {@link JitsiRemoteTrack} instance.
   */
  | 'rtc.remote_track_removed'
  // FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event
  // (currently implemented for local tracks only)
  | 'rtc.remote_track_unmute'
  /**
   * Indicates error while set local description.
   */
  | 'rtc.set_local_description_failed'
  /**
   * Indicates error while set remote description.
   */
  | 'rtc.set_remote_description_failed'
  | 'rtc.audio_output_device_changed'
  | 'rtc.device_list_changed'
  /**
   * Indicates that the list with available devices will change.
   */
  | 'rtc.device_list_will_change'
  | 'rtc.device_list_available'
  /**
   * Indicates that a message from another participant is received on
   * data channel.
   */
  | 'rtc.endpoint_message_received'
  /**
   * Indicates that the remote endpoint stats have been received on data channnel.
   */
  | 'rtc.endpoint_stats_received'
  /**
   * Designates an event indicating that the local ICE username fragment of
   * the jingle session has changed.
   * The first argument of the vent is <tt>TraceablePeerConnection</tt> which
   * is the source of the event.
   * The second argument is the actual "ufrag" string.
   */
  | 'rtc.local_ufrag_changed'
  /**
   * Designates an event indicating that the local ICE username fragment of
   * the jingle session has changed.
   * The first argument of the vent is <tt>TraceablePeerConnection</tt> which
   * is the source of the event.
   * The second argument is the actual "ufrag" string.
   */
  | 'rtc.remote_ufrag_changed'

  /**
   * Custom server messages
   */
  | `rtc.datachannel.${string}`;

type JitsiRTCEventType = JitsiRTCEventType$1;
type JitsiXmppEventType = JitsiXmppEventType$1;
type JitsiOutputType = 'video' | 'audio';
type JitsiVideoType = 'camera' | 'desktop';

// Not typed yet
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type UntypedCallback = (...data: any[]) => void;

type PayloadObject = object;

interface JitsiTrack {
  containers: HTMLMediaElement[];
  disposed: boolean;
  track: MediaStreamTrack;
  stream: MediaStream;
  videoType?: JitsiVideoType;
  ssrc?: number;

  // For local tracks
  maxEnabledResolution?: number;

  isAudioTrack(): boolean;

  isWebRTCTrackMuted(): boolean;

  isVideoTrack(): boolean;

  isLocal(): boolean;

  isLocalAudioTrack(): boolean;

  isActive(): boolean;

  isMuted(): boolean;

  getType(): JitsiOutputType;

  getOriginalStream(): MediaStream | null;

  getStreamId(): string | null;

  getTrack(): MediaStreamTrack;

  getTrackLabel(): string;

  getTrackId(): string | null;

  getUsageLabel(): JitsiVideoType | 'mic' | 'default';

  getId(): string | null;

  getParticipantId(): string | null;

  getSourceName(): string | null;

  attach(element: HTMLVideoElement | HTMLAudioElement): void;

  detach(element: HTMLVideoElement | HTMLAudioElement): void;

  dispose(): Promise<void>;

  // audioLevel: value between 0 and 1
  setAudioLevel(audioLevel: number, tpc: TraceablePeerConnection): void;

  getMSID(): string | null;

  setAudioOutput(audioOutputDeviceId: string): Promise<void>;

  addEventListener(event: string, callback: UntypedCallback): void;

  removeEventListener(event: string, callback: UntypedCallback): void;
}

interface JitsiRemoteTrack extends JitsiTrack {
  isP2P: boolean;

  setMute(value: boolean): void;

  getSSRC(): number; // synchronization source identifier
  _getStatus(): `readyState: ${MediaStreamTrackState}, muted: ${boolean}, enabled: ${boolean}`;

  toString(): `RemoteTrack[userID: ${string}, type: ${JitsiOutputType}, ssrc: ${number}, p2p: ${boolean}, status: ${ReturnType<
    JitsiRemoteTrack['_getStatus']
  >}]`;
}

type JitsiLocalTrackEffect = Readonly<{
  isEnabled: (track: JitsiLocalTrack) => boolean;
  isMuted?: () => boolean;
  setMuted?: (muted: boolean) => void;
  startEffect: (stream: MediaStream) => MediaStream | null;
  stopEffect: () => void;

  // Jazz custom prop
  key?: string;
  // Jazz custom prop
  order?: 'start' | 'end';
}>;

interface JitsiLocalTrack extends JitsiTrack {
  _realDeviceId: string;
  deviceId: string;

  isEnded(): boolean;

  getCameraFacingMode(): 'environment' | 'user' | undefined;

  getDeviceId(): string;

  setEffect(effect: JitsiLocalTrackEffect | undefined): Promise<void>;

  setConference(conference: JitsiConference | null): void;

  mute(): Promise<void>;

  unmute(): Promise<void>;

  stopStream(): void;

  toString(): string;

  _originalStream: MediaStream | null;
  rtcId: number;
  conference: JitsiConference | null;

  // Jazz custom
  addEffect(effect: JitsiLocalTrackEffect): Promise<void>;
  // Jazz custom
  removeEffect(key?: string): Promose<void>;
  // Jazz custom
  removeEffects(): Promose<void>;
}

type TPCGroupInfo = {
  /** the SSRC groups semantics */
  semantics: string;

  /** group's SSRCs in order where the first one is group's primary SSRC,
   * the second one is secondary (RTX) and so on... */
  ssrcs: Array<number>;
};

type TPCSSRCInfo = {
  /** an array which holds all track's SSRCs */
  ssrcs: Array<number>;

  /** an array stores all track's SSRC groups */
  groups: Array<TPCGroupInfo>;
};

type TraceablePeerConnection = {
  peerconnection?: RTCPeerConnection;
  localSSRCs: Map<string, TPCSSRCInfo>;
  getLocalSSRC(localTrack: JitsiTrack): number | undefined;
  isSimulcastOn(): boolean;
  getActiveSimulcastStreams(): number;
  getTargetVideoBitrates(): Record<string, number>;
  getConfiguredVideoCodec(): string;
  configureSenderVideoEncodings(): void;
};

interface JitsiConnectionOptions {
  billingId?: string;

  hosts: {
    domain: string;
    muc?: string;
    bridge?: string;
    focus?: string;
  };
  bosh?: string;
  websocket?: string;
  clientNode?: string;
  serviceUrl?: string;
  confID?: string;
  siteID?: string;
  startSilent?: boolean;
  applicationName?: string;
  resolution?: number;
  constraints?: {
    video: {
      aspectRatio: number;
      height: {
        ideal: number;
        max: number;
        min: number;
      };
      width: {
        ideal: number;
        max: number;
        min: number;
      };
    };
  };
  enableWebsocketResume?: boolean;
  enableNoAudioDetection?: boolean;
  enableNoisyMicDetection?: boolean;
  enableTalkWhileMuted?: boolean;
  enableUnifiedOnChrome?: boolean;
  enableLayerSuspension?: boolean;
  channelLastN?: number;
  disableSimulcast?: boolean;

  audioQuality?: {
    stereo?: boolean;
    opusMaxAverageBitrate?: number; // 6000 - 510000
  };

  videoQuality?: {
    preferredCodec?: string;
    enforcePreferredCodec?: boolean;
    disabledCodec?: string;
    maxBitratesVideo?: {
      low: number;
      standard: number;
      high: number;
    };
    desktopBitrate?: number;
    configureVP9?: boolean; // custom flag for jazz. see patch 28_vp9-encodings.
    multiplierVP9?: number; // custom flag for jazz. see patch 28_vp9-encodings.
  };
  p2p?: {
    enabled?: boolean;
    disabledCodec?: string;
    preferredCodec?: string;
  };
  enableForcedReload?: boolean;
  enableIceRestart?: boolean;
  desktopSharingFrameRate?: {
    min: number;
    max: number;
  };

  /** Use TURN/UDP servers for the jitsi-videobridge connection */
  useTurnUdp?: boolean;
  useNewBandwidthAllocationStrategy?: boolean;

  websocketKeepAlive?: number;
}

interface JitsiConferenceOptions extends Omit<JitsiConnectionOptions, 'p2p'> {
  openBridgeChannel?: string;
  startSilent?: boolean;
  p2p?: {
    enabled?: boolean;
  };
}

interface JitsiUser {
  getId(): string;

  getJid(): string;

  getDisplayName(): string | undefined;

  getRole(): string;

  isAudioMuted(): boolean;

  isVideoMuted(): boolean;

  getStatus(): string;

  getConnectionStatus(): string;

  hasAnyVideoTrackWebRTCMuted(): boolean;

  isHidden(): boolean;

  isReplacing(): boolean;

  isReplaced(): boolean;

  getBotType(): string | undefined;

  getTracks(): Array<JitsiTrack>;
}

interface JitsiCommand {
  value?: string;
  attributes?: Record<string, string | undefined>;
  children?: JitsiCommand[];
  tagName?: string;
}

interface DownloadUploadStats {
  download: number;
  upload: number;
}

interface JitsiBridgeStats {
  bitrate?: DownloadUploadStats & {
    audio?: DownloadUploadStats;
    video?: DownloadUploadStats;
  };
  connectionQuality?: number;
  packetLoss?: {
    total: number;
    download: number;
    upload: number;
  };
}

interface JitsiConnectionQuality {
  _remoteStats: Record<string, JitsiBridgeStats>;

  getStats(): JitsiBridgeStats;
}

interface JitsiStatistics {
  addConnectionStatsListener(callback: () => void): void;

  removeConnectionStatsListener(callback: () => void): void;

  addMediaNotFlowingListener(callback: (track: JitsiRemoteTrack) => void): void;

  removeMediaNotFlowingListener(
    callback: (track: JitsiRemoteTrack) => void,
  ): void;
}

type JitsiListenable<EventName> = {
  addListener(eventName: EventName, listener: UntypedCallback): () => void;
  removeListener(eventName: EventName, listener: UntypedCallback);

  // Aliases
  addEventListener: JitsiListenable<EventName>['addListener'];
  removeEventListener: JitsiListenable<EventName>['removeListener'];
  on: JitsiListenable<EventName>['addListener'];
  off: JitsiListenable<EventName>['removeListener'];
};

type StropheConnectionHandlerRef = unknown;

type JitsiXmppConnection = {
  getJid(): string;

  pingDomain: string | undefined | null;

  ping: {
    ping(
      jid: string,
      success: () => unknown,
      error: () => unknown,
      timeout: number,
    ): void;
  };

  _stropheConn: {
    _doDisconnect(condition: string): void;
    _proto: {
      _abortAllRequests(): void;
    };

    addHandler(
      handler: (presence: Node) => void,
      ns: string | null,
      name: string,
      type: string | null,
      id: string | null,
      from?: string,
      options?: { matchBare?: boolean },
    ): StropheConnectionHandlerRef;

    deleteHandler(handlerRef: StropheConnectionHandlerRef): void;
  };

  disconnect(reason?: string): void;
  flush(): void;
  getXmppLog(): Array<[number, string, string]>;
  connection: {
    emuc: {
      addEventListener(event: string, callback: UntypedCallback): () => void;
      removeEventListener(event: string, callback: UntypedCallback): void;
      rooms: Record<string, any>;
    };
  };
};

type JitsiXmppListenable = JitsiListenable<JitsiXmppEventType>;

type JitsiXmpp = JitsiXmppListenable & {
  roomjid: string;
  myroomjid: string;
  connection: JitsiXmppConnection;
  members: Record<string, unknown>;

  /** @deprecated It doesn't work */
  ping(timeout: number): Promise<boolean>;

  /** Flush presence state */
  sendPresence(): void;

  kick(jid: string, reason?: string): void;

  lobby?: {
    lobbyRoom?: Omit<JitsiXmpp, 'lobby'>;
  };
};

type LobbyRoom = {
  isSupported: () => boolean;
  enable: () => Promise<unknown>;
  disable: () => void;
  setLobbyRoomJid: (jid: string) => void;
  join: (displayName?: string, email?: string) => Promise<unknown>;
  denyAccess: (id: string) => void;
  approveAccess: (id: string) => void;
};

type ChatRoom = JitsiXmpp & {
  getLobby(): LobbyRoom | undefined;
  lobby: LobbyRoom | undefined;
};

type JitsiPeerConnections = Map<
  number,
  {
    peerconnection: RTCPeerConnection;
  }
>;

type BridgeChannel = {
  isOpen: () => boolean;
  _retryWebSocketConnection: ({ code: number, reason: string }) => void;
};

type JitsiMediaType = 'audio' | 'presenter' | 'video';

type JitsiRTC = JitsiListenable<JitsiRTCEventType> & {
  peerConnections: JitsiPeerConnections;
  _channel?: BridgeChannel | null;

  sendChannelMessage<Payload extends object = object>(
    to: string | undefined,
    payload: Payload,
  ): void;

  getLocalTracks(mediaType?: JitsiMediaType): Array<JitsiLocalTrack>;
  getRemoteTracks(mediaType?: JitsiMediaType): Array<JitsiRemoteTrack>;
};

interface JitsiConference {
  lastDominantSpeaker: string | null;
  options: { name: string };
  connectionQuality: JitsiConnectionQuality;
  participants: Record<string, JitsiUser>;
  statistics: JitsiStatistics;
  room: ChatRoom | undefined;
  rtc: JitsiRTC;
  connection: JitsiConnection;
  xmpp: JitsiXmppConnection;

  on(event: string, callback: UntypedCallback): void;

  off(event: string, callback: UntypedCallback): void;

  addEventListener(event: string, callback: UntypedCallback): void;

  removeEventListener(event: string, callback: UntypedCallback): void;

  enableLobby(): Promise<unknown>;

  disableLobby(): void;

  isLobbySupported(): boolean;

  myLobbyUserId(): string;

  joinLobby(name: string, email?: string): void;

  lobbyDenyAccess(id: string): void;

  lobbyApproveAccess(id: string): void;

  join(
    password?: string,
    participantName?: string,
    joinedPayload?: unknown, // custom parameter for jazz.
  ): void;

  leave(): Promise<void>;

  addTrack(track: JitsiTrack): Promise<void>;

  removeTrack(track: JitsiTrack): Promise<void>;

  replaceTrack(
    oldTrack: JitsiTrack | null,
    newTrack: JitsiTrack | null,
  ): Promise<void>;

  getLocalTracks(
    mediaType?: 'video' | 'audio' | 'presenter',
  ): Array<JitsiLocalTrack>;

  getLocalAudioTrack(): JitsiLocalTrack | null;

  getLocalVideoTrack(): JitsiLocalTrack | null;

  getPhoneNumber(): string;

  getPhonePin(): string;

  myUserId(): string;

  getParticipantById(participantId: string): JitsiUser | undefined;

  selectParticipant(participantId: string): void;

  getRole(): 'moderator' | 'none';

  isModerator(): boolean;

  isHidden(): boolean | undefined | null;

  lock(password: string): Promise<void>; // moderator only
  unlock(): Promise<void>; // moderator only
  setStartMutedPolicy(policy: { video: boolean; audio: boolean }): void; // moderator only
  getStartMutedPolicy(): { video: boolean; audio: boolean };

  setReceiverVideoConstraint(resolution: number): void;

  setSenderVideoConstraint(resolution: number | undefined): void;

  setSubject(subject: string): void; // moderator only
  setDisplayName(name: string): void;

  sendMessage(text: string, to?: string): void;

  sendJsonMessage(data: Object, from?: string, to?: string): Promise<void>;

  sendEndpointMessage(to: string, payload: PayloadObject): void;

  broadcastEndpointMessage(payload: PayloadObject): void;

  setLastN(count: number): void;

  /**
   Отправляет команды всем, включая себя, иногда команды могут приходить повторно, с теми же
   данными
   */
  sendCommand(name: string, values: JitsiCommand): void;

  removeCommand(name: string): void;

  sendCommandOnce(name: string, values: JitsiCommand): void;

  addCommandListener(
    name: string,
    handler: (values: JitsiCommand, participantId: string) => void,
  ): void;

  removeCommandListener(
    name: string,
    handler: (values: JitsiCommand, participantId: string) => void,
  ): void;

  setDesktopSharingFrameRate(maxFps: number): void;

  getActivePeerConnection(): TraceablePeerConnection | undefined | null;

  getParticipants(): Array<JitsiUser>;

  muteParticipant(participantId: string, mediaType: JitsiMediaType): void;

  kickParticipant(participantId: string, reason?: string): void;

  _setupNewTrack(track: JitsiLocalTrack): void;

  _onTrackAttach(track: JitsiLocalTrack, container: HTMLElement): void;

  _removeLocalTrackFromPc(track: JitsiLocalTrack): Promise<void>;

  _addLocalTrackToPc(track: JitsiLocalTrack): Promise<void>;

  _setTrackMuteStatus(
    mediaType: string,
    track: JitsiLocalTrack,
    isMuted: boolean,
  ): boolean;

  _sendBridgeVideoTypeMessage(track: JitsiLocalTrack): void;
}

interface JitsiConnectionConnectOptions {
  id: string;
  password: string;
}

type JitsiConnection = {
  new (
    appId: string,
    token: string | undefined | null,
    options: JitsiConnectionOptions,
  ): JitsiConnection;
  addEventListener(event: string, callback: UntypedCallback): void;
  removeEventListener(event: string, callback: UntypedCallback): void;
  connect(options?: JitsiConnectionConnectOptions): void;
  initJitsiConference(
    name: string,
    options: JitsiConferenceOptions,
  ): JitsiConference;
  disconnect(): Promise<void>;
  getLogs(): any;
  addFeature(feature: string, submit?: boolean): void;
  xmpp: JitsiXmppConnection;
};

type ConnectionInterruptedReason =
  | 'unknown'
  | 'iceConnection'
  | 'xmppConnection'
  | 'jvbConnection';

type DisplayCaptureMode = 'highQuality' | 'maxFPS';

type EventToMap<
  T extends {
    type: string;
    payload?: unknown;
  },
> = {
  [K in T as K['type']]: Extract<
    T,
    {
      type: K['type'];
    }
  >['payload'];
};

type MediaType$1 = UserAudioMediaType | UserVideoMediaType | DisplayMediaType$1;
type UserMediaType$1 = UserAudioMediaType | UserVideoMediaType;
type UserAudioMediaType = 'audio';
type UserVideoMediaType = 'video';
type DisplayMediaType$1 = 'displayScreen';
type JazzVideoResolution$1 =
  | '2160'
  | '4k'
  | '1080'
  | 'fullhd'
  | '720'
  | 'hd'
  | '540'
  | 'qhd'
  | '480'
  | 'vga'
  | '360'
  | '240'
  | '180';

type MediaPermission = 'granted' | 'denied' | 'prompt';
type UserMediaType = UserMediaType$1;
type DisplayMediaType = DisplayMediaType$1;
type MediaType = MediaType$1;
type UserMediaPermissionState = Readonly<
  Record<UserMediaType, MediaPermission>
>;
type DisplayMediaPermissionState = Readonly<
  Record<DisplayMediaType, MediaPermission>
>;
type GroupedDevices = {
  ['audioInput']: LocalAudioInputDevice[];
  ['audioOutput']: LocalAudioOutputDevice[];
  ['videoInput']: LocalVideoInputDevice[];
};
type LocalMediaDeviceKind = 'audioInput' | 'audioOutput' | 'videoInput';
type LocalMediaDeviceId = string;
type BaseMediaDeviceInfo = {
  deviceId: LocalMediaDeviceId;
  groupId?: string;
  label: string | '';
};
type LocalAudioInputDevice = Readonly<
  {
    kind: 'audioInput';
  } & BaseMediaDeviceInfo
>;
type LocalAudioOutputDevice = Readonly<
  {
    kind: 'audioOutput';
  } & BaseMediaDeviceInfo
>;
type LocalVideoInputDevice = Readonly<
  {
    kind: 'videoInput';
  } & BaseMediaDeviceInfo
>;
type LocalMediaDevice =
  | LocalAudioInputDevice
  | LocalAudioOutputDevice
  | LocalVideoInputDevice;
type LocalMediaDevicesEvent = Readonly<
  | LocalMediaDevicesEventDeviceListChanged
  | LocalMediaDevicesEventPermissionsChanged
  | LocalMediaDevicesEventAudioPermissionsChanged
  | LocalMediaDevicesEventVideoPermissionsChanged
  | LocalMediaDevicesEventRequestDevicePermissions
  | LocalMediaDevicesEventErrorDevicePermissions
  | LocalMediaDevicesEventSuccessDevicePermissions
>;
type LocalMediaDevicesEvents = EventToMap<LocalMediaDevicesEvent>;
type LocalMediaDevicesEventDeviceListChanged = {
  type: 'deviceListChanged';
  payload: {
    devices: ReadonlyArray<LocalMediaDevice>;
    groupedDevices: GroupedDevices;
    prevGroupedDevices: GroupedDevices;
    added: ReadonlyArray<LocalMediaDevice>;
    removed: ReadonlyArray<LocalMediaDevice>;
    groupedAddedDevices: GroupedDevices;
    groupedRemovedDevices: GroupedDevices;
  };
};
type LocalMediaDevicesEventPermissionsChanged = {
  type: 'permissionsChanged';
  payload: UserMediaPermissionState;
};
type LocalMediaDevicesEventRequestDevicePermissions = {
  type: 'requestDevicePermissions';
  payload: {
    mediaTypes: UserMediaType[];
  };
};
type LocalMediaDevicesEventErrorDevicePermissions = {
  type: 'errorDevicePermissions';
  payload: {
    type: MediaPermissionErrorType;
    kind: MediaPermissionErrorKind[];
    message: string;
  };
};
type LocalMediaDevicesEventSuccessDevicePermissions = {
  type: 'successDevicePermissions';
  payload: {
    mediaTypes: UserMediaType[];
    state: UserMediaPermissionState;
  };
};
type LocalMediaDevicesEventAudioPermissionsChanged = {
  type: 'audioPermissionsChanged';
  payload: {
    audio: MediaPermission;
  };
};
type LocalMediaDevicesEventVideoPermissionsChanged = {
  type: 'videoPermissionsChanged';
  payload: {
    video: MediaPermission;
  };
};
type MediaPermissionErrorType = 'browser' | 'OS' | 'unknown';
type MediaPermissionErrorKind = 'audio' | 'video';

type Primitive = string | number | boolean | bigint | symbol | null | undefined;
/**
 * Объединяет сложные типы
 *
 * @example
 * type GoodUnion = DeepUnion<
 * { arr: [{ a: number; b: number }] },
 * { arr: [{ a: string }] }
 * >;
 *
 * const goodUnion: GoodUnion = { arr: [{ a: 1, b: 2 }] };
 *
 * type BadUnion = { arr: [{ a: number; b: number }] } & { arr: [{ a: string }] };
 *
 * const badUnion: BadUnion = { arr: [{ a: 1, b: 2 }] };
 */
type DeepUnion$1<T, U> = T extends Primitive
  ? T | U
  : U extends Primitive
    ? T | U
    : [T, U] extends [ReadonlyArray<infer TItem>, ReadonlyArray<infer UItem>]
      ? ReadonlyArray<DeepUnion$1<TItem, UItem>>
      : [T, U] extends [Array<infer TItem>, ReadonlyArray<infer UItem>]
        ? ReadonlyArray<DeepUnion$1<TItem, UItem>>
        : [T, U] extends [ReadonlyArray<infer TItem>, Array<infer UItem>]
          ? ReadonlyArray<DeepUnion$1<TItem, UItem>>
          : [T, U] extends [Array<infer TItem>, Array<infer UItem>]
            ? Array<DeepUnion$1<TItem, UItem>> // Обработка объектов
            : {
                [K in keyof (T & U)]: K extends keyof T
                  ? K extends keyof U
                    ? DeepUnion$1<T[K], U[K]>
                    : T[K]
                  : K extends keyof U
                    ? U[K]
                    : never;
              } & {
                [K in RequiredKeys<T> | RequiredKeys<U>]-?: K extends keyof (T &
                  U)
                  ? K extends keyof T
                    ? K extends keyof U
                      ? DeepUnion$1<T[K], U[K]>
                      : T[K]
                    : K extends keyof U
                      ? U[K]
                      : never
                  : never;
              };
type RequiredKeys<T> = {
  [K in keyof T]-?: undefined extends T[K] ? never : K;
}[keyof T];
/**
 * Объединяет массив сложных типов
 *
 * @example
 * type GoodUnion = DeepUnionAll<[
 * { arr: [{ a: number; b: number }] },
 * { arr: [{ a: string }] }
 * ]>;
 */
type DeepUnionAll$1<T extends unknown[]> = T extends [
  infer First,
  ...infer Rest,
]
  ? Rest extends []
    ? First
    : DeepUnion$1<First, DeepUnionAll$1<Rest>>
  : never;

/**
 * @param PropertyName string
 * @param MergeType 'intersection' | 'union' | 'deepUnion', default: 'intersection'
 */
type PropertyExtender<
  T extends Record<string, unknown>[],
  PropertyName extends string,
  MergeType extends 'intersection' | 'union' | 'deepUnion' = 'intersection',
> = T extends [infer First, ...infer Rest]
  ? Rest extends Record<string, unknown>[]
    ? First extends {
        [key in PropertyName]: infer P1;
      }
      ? IsUnion<P1> extends true
        ? P1 | PropertyExtender<Rest, PropertyName, 'union'>
        : IsPrimitive<P1> extends true
          ? P1 | PropertyExtender<Rest, PropertyName, 'union'>
          : MergeType extends 'union'
            ? P1 | PropertyExtender<Rest, PropertyName, 'union'>
            : MergeType extends 'intersection'
              ? P1 & PropertyExtender<Rest, PropertyName, 'intersection'>
              : DeepUnion$1<
                  P1,
                  PropertyExtender<Rest, PropertyName, 'deepUnion'>
                >
      : PropertyExtender<Rest, PropertyName, MergeType>
    : MergeType extends 'union'
      ? never
      : {}
  : MergeType extends 'union'
    ? never
    : {};
type TakeProperty<
  T,
  PropertyName extends string,
  PropertyValue = Record<string, unknown>,
  Alternative = {},
> = T extends {
  [key in PropertyName]: PropertyValue;
}
  ? T[PropertyName]
  : Alternative;
type MakeExtender<
  TBase extends object,
  TExt extends {
    [K in keyof TExt]: K extends keyof TBase
      ? TExt[K] extends TBase[K]
        ? TExt[K]
        : never
      : never;
  },
> = TExt;
type IsUnion<T, U = T> = T extends any
  ? [U] extends [T]
    ? false
    : true
  : never;
type IsPrimitive<T> = T extends string
  ? true
  : T extends number
    ? true
    : T extends boolean
      ? true
      : false;

type JazzRoomExtender = {
  participant?: Record<string, unknown>;
  permissions?: Record<string, unknown>;
  permissionRequests?: Record<string, unknown>;
  error?: {
    type: string;
  } & Omit<Record<string, unknown>, 'type'>;
};

type Query<T> = {
  /**
   * @deprecated use classic exec function without .get()
   */
  readonly get: () => T;
  /**
   * @deprecated use handleAtom
   */
  readonly value$: Observable<T>;
};
/**
 * type Query is deprecated, the name of the future reactive data is Atom
 */
type QueryAtom<T> = Atom<T> & Query<T>;

declare class JazzRoomError<
  T extends JazzRoomErrorReason = JazzRoomErrorReason,
> extends Error {
  readonly reason: T;
  constructor(message: string, reason: T);
}
declare class AuthorizationRequiredError extends Error {
  constructor();
}
declare class UserNameRequiredError extends Error {
  constructor();
}
declare class RoomConnectedError extends Error {
  constructor();
}
declare class PermissionDeniedError extends Error {
  constructor(permission: string);
}

declare const LOCAL_MEDIA_DEVICE_KIND: {
  readonly AUDIO_INPUT: 'audioInput';
  readonly AUDIO_OUTPUT: 'audioOutput';
  readonly VIDEO_INPUT: 'videoInput';
};
declare const MEDIA_PERMISSION: {
  readonly GRANTED: 'granted';
  readonly DENIED: 'denied';
  readonly PROMPT: 'prompt';
};
declare const DISPLAY_MEDIA_TYPE: {
  readonly SCREEN: 'displayScreen';
};
declare const USER_MEDIA_TYPE: {
  readonly AUDIO: 'audio';
  readonly VIDEO: 'video';
};

type OnlyIfExists<T, U extends T> = U;

type LocalTrackEffect = JitsiLocalTrackEffect;
type JazzVideoResolution = JazzVideoResolution$1;

type JazzRoomEventLocalParticipantId = Readonly<{
  type: 'localParticipantId';
  payload: {
    participantId: JazzRoomParticipantId;
  };
}>;
type JazzRoomEventParticipants<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'participants';
  payload: {
    participants: JazzRoomParticipant<T>[];
  };
}>;
type JazzRoomEventParticipantUpdate<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'participantUpdate';
  payload: {
    participant: {
      id: JazzRoomParticipantId;
    } & Partial<Omit<JazzRoomParticipant<T>, 'id'>>;
  };
}>;
type JazzRoomEventParticipantLeft<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'participantLeft';
  payload: {
    participant: JazzRoomParticipant<T>;
  };
}>;
type JazzRoomEventParticipantJoined<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'participantJoined';
  payload: {
    participant: JazzRoomParticipant<T>;
  };
}>;
type JazzRoomParticipantRole = StringEnum<'owner' | 'member' | 'moderator'>;
type JazzRoomParticipantId = string;
type JazzRoomParticipantCommon = {
  id: JazzRoomParticipantId;
  name: string;
  isGuest: boolean;
  role: JazzRoomParticipantRole;
  joinedDate: number;
  email?: string;
};
type JazzRoomParticipantBotType = string;
type JazzRoomParticipantBotDetails = {
  type: JazzRoomParticipantBotType;
};
type JazzRoomParticipantBot<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  JazzRoomParticipantCommon & {
    bot: JazzRoomParticipantBotDetails;
  } & PropertyExtender<T, 'participant'>;
type JazzRoomParticipantUser<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = JazzRoomParticipantCommon & {
  bot?: undefined;
} & PropertyExtender<T, 'participant'>;
type JazzRoomParticipant<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  | JazzRoomParticipantBot<T>
  | JazzRoomParticipantUser<T>;

type RoomMediaSourceEventStateBase = {
  isMuted: boolean;
  stream: MediaStream | undefined;
};
type RoomMediaSourceEvents = {
  addTrack: RoomMediaSourceEventStateBase & {
    stream: MediaStream;
  };
  removeTrack: RoomMediaSourceEventStateBase & {
    stream: MediaStream | undefined;
  };
  /**
   * Обновление трека внутри стрима
   */
  updateTrack: {
    isMuted: boolean;
    stream: MediaStream;
  };
  /**
   * Обновление mute/unmute состояния
   */
  muteChange: RoomMediaSourceEventStateBase;
  trackInfo: RoomMediaSourceEventStateBase;
};
type RoomMediaSourceStateBase = {
  stream: MediaStream | undefined;
  trackId: string | undefined;
  ssrc: number | undefined;
  isMuted: boolean;
  isLocal: boolean;
};
type RoomMediaSourceStateBaseWatchedReadonly = {
  stream: Atom<MediaStream | undefined>;
  trackId: Atom<string | undefined>;
  ssrc: Atom<number | undefined>;
  isMuted: Atom<boolean>;
};
type RoomMediaSource = {
  id: Readonly<string>;
  mediaType: Readonly<MediaType>;
  participantId: Readonly<JazzRoomParticipantId>;
  isLocal: boolean;
  on: TransportRoot<RoomMediaSourceEvents>['on'];
  once: TransportRoot<RoomMediaSourceEvents>['once'];
  off: TransportRoot<RoomMediaSourceEvents>['off'];
};
type RoomMediaSourcesState = ReadonlyMap<
  JazzRoomParticipantId,
  ReadonlyMap<MediaType, RoomMediaSourceStateBase>
>;
type RoomMediaSourcesGettingMediaSource = RoomMediaSource &
  RoomMediaSourceStateBaseWatchedReadonly;

type JazzRoomStatus = JazzRoomStatusMap[keyof JazzRoomStatusMap];
type JazzRoomStatusMap = {
  readonly CONNECTED: 'connected';
  readonly CONNECTING: 'connecting';
  readonly DISCONNECTING: 'disconnecting';
  readonly DISCONNECTED: 'disconnected';
  readonly ERROR: 'error';
};
type JazzRoomConnectionStatus =
  JazzRoomConnectionStatusMap[keyof JazzRoomConnectionStatusMap];
type JazzRoomConnectionStatusMap = {
  readonly CONNECTED: 'connected';
  readonly CONNECTING: 'connecting';
  readonly DISCONNECTED: 'disconnected';
  readonly FAILED: 'failed';
};
type JazzRoomReconnectingReason =
  | ConnectionInterruptedReason
  | 'errorConferenceRestarted'
  | 'suspendDetected'
  | 'network';
type JazzRoomAudioSource = 'user' | 'display';
type JazzRoomVideoSource = 'user' | 'display';
/** @deprecated please use width and height */
type JazzRoomQuality = 'high' | 'medium' | 'low';
type JazzRoomVideoQuality = Readonly<{
  /** @deprecated please use width and height */
  quality?: JazzRoomQuality;
  height: number;
  width: number;
}>;
type JazzRoomMediaSourceState = Readonly<{
  isMuted: boolean;
  stream?: MediaStream;
}>;
type JazzRoomAudioSourceState = Readonly<
  Record<JazzRoomAudioSource, JazzRoomMediaSourceState | undefined>
>;
type JazzRoomVideoSourceState = Readonly<
  Record<JazzRoomVideoSource, JazzRoomMediaSourceState | undefined>
>;
type JazzRoomVideoRequest = Readonly<
  {
    source: JazzRoomVideoSource;
  } & JazzRoomVideoQuality
>;
type JazzRoomSettings = {
  title: string;
  isGuestEnabled: boolean;
  isNext: boolean | undefined;
};
type JazzRoomSettingsUpdates = {
  title: string;
  guestEnabled: boolean;
};
type JazzRoomSettingsUpdate = Partial<JazzRoomSettingsUpdates>;
type JazzRoomSettingsQueries = {
  title: QueryAtom<string | undefined>;
  isGuestEnabled: QueryAtom<boolean | undefined>;
  isNext: Atom<boolean | undefined>;
};
type JazzRoomUserPermissionRequestKey<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> =
  | 'canShareAudio'
  | 'canShareCamera'
  | 'canShareMedia'
  | 'canSendReaction'
  | keyof PropertyExtender<T, 'permissionRequests'>;
type JazzRoomUserPermissionRequest<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = {
  permissionKey: JazzRoomUserPermissionRequestKey<T>;
  created: Timestamp;
  canRequestAgain: boolean;
};
type JazzRoomUserPermissionKey<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> =
  | 'canEditOwnName'
  | 'canEditRoomPolicy'
  | 'canEditRoomTitle'
  | 'canFinishCall'
  | 'canGrantPermission'
  | 'canKickUser'
  | 'canMuteUser'
  | 'canRequestPermission'
  | 'canShareAudio'
  | 'canShareCamera'
  | 'canShareMedia'
  | 'canToggleGuestEnabled'
  | 'canSendReaction'
  | 'canManageLobby'
  | 'canInvite'
  | keyof PropertyExtender<T, 'permissions'>;
type JazzRoomUserPermissions<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Record<JazzRoomUserPermissionKey, boolean> &
  PropertyExtender<T, 'permissions'>;
type JazzRoomPartialUserPermissions<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Partial<JazzRoomUserPermissions<T>>;
type NotAllowedError = {
  type: 'notAllowed';
};
type AccessByPermissionError = {
  type: 'accessByPermission';
};
type MaxMeetingCountExceededError = {
  type: 'MAX_MEETING_COUNT_EXCEEDED';
};
type NetworkError = {
  type: 'network';
};
type OpenConnectionError = {
  type: 'openConnection';
};
type RoomNotFoundError = {
  type: 'roomNotFound';
};
type RoomNotSupportedByClientError = {
  type: 'roomNotSupportedByClientError';
};
type UnauthorizedError = {
  type: 'unauthorized';
};
type ForbiddenError = {
  type: 'forbidden';
};
type RoomCapacityExceededError = {
  type: 'roomCapacityExceeded';
  payload: {
    roomCapacity?: number;
  };
};
type UnknownError = {
  type: 'unknown';
};
type JazzRoomErrorReason<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  | NotAllowedError
  | AccessByPermissionError
  | MaxMeetingCountExceededError
  | NetworkError
  | OpenConnectionError
  | RoomNotFoundError
  | RoomNotSupportedByClientError
  | UnauthorizedError
  | ForbiddenError
  | RoomCapacityExceededError
  | UnknownError
  | PropertyExtender<T, 'error', 'union'>;
type JazzRoomKickedReason = StringEnum<
  | 'callEnded'
  | 'kicked'
  | 'exceededMaxConferenceCapacity'
  | 'exceededMaxConferenceViewersCapacity'
  | 'exceededMaxConferenceDuration'
  | 'guestsNotAllowed'
>;
type JazzRoomKickedPayload = {
  reason: JazzRoomKickedReason;
};
type JazzRoomEventKicked = {
  type: 'kicked';
  payload: JazzRoomKickedPayload;
};
type JazzRoomLeaveReason = 'localEnd' | 'callEnd';
type JazzRoomEventLeave = {
  type: 'leave';
  payload: {
    reason: JazzRoomLeaveReason;
  };
};
type JazzRoomEventAddTrack = Readonly<{
  type: 'addTrack';
  payload: {
    stream: MediaStream;
    mediaType: MediaType;
    participantId: JazzRoomParticipantId;
    isMuted: boolean;
    isLocal: boolean;
  };
}>;
type JazzRoomEventRemoveTrack = Readonly<{
  type: 'removeTrack';
  payload: {
    stream: MediaStream;
    mediaType: MediaType;
    participantId: JazzRoomParticipantId;
    isMuted: boolean;
    isLocal: boolean;
  };
}>;
type JazzRoomEventTrackMuteChanged = Readonly<{
  type: 'trackMuteChanged';
  payload: {
    isMuted: boolean;
    stream: MediaStream;
    mediaType: MediaType;
    participantId: JazzRoomParticipantId;
    changedByParticipantId: string;
    isLocal: boolean;
  };
}>;
type JazzRoomEventTrackMuteChangeRejected = Readonly<{
  type: 'trackMuteChangeRejected';
  payload: {
    stream: MediaStream;
    mediaType: MediaType;
  };
}>;
type JazzRoomEventTrackAddRejected = Readonly<{
  type: 'trackAddRejected';
  payload: {
    stream: MediaStream;
    mediaType: MediaType;
  };
}>;
type JazzRoomEventTrackUpdated = Readonly<{
  type: 'trackUpdated';
  payload: {
    stream: MediaStream;
    mediaType: MediaType;
    participantId: JazzRoomParticipantId;
    isMuted: boolean;
    isLocal: boolean;
  };
}>;
type JazzRoomEventRemoteTrackInfo = Readonly<{
  type: 'remoteTrackInfo';
  payload: {
    participantId: JazzRoomParticipantId;
    mediaType: MediaType;
    isMuted: boolean;
  };
}>;
type JazzRoomEventSettingsChanged = Readonly<{
  type: 'settingsChanged';
  payload: Partial<{
    title: string;
    isGuestEnabled: boolean;
  }>;
}>;
type JazzRoomParamsUpdate = Readonly<{
  /**
   * @deprecated use roomId
   */
  conferenceId: JazzRoomConferenceId;
  /**
   * @deprecated use roomPassword
   */
  conferencePassword: string;
  roomId: JazzRoomId;
  roomPassword: string;
  meetingId: JazzMeetingId | undefined;
  roomType: JazzRoomType;
}>;
type JazzRoomEventParamsChanged = Readonly<{
  type: 'paramsChanged';
  payload: JazzRoomParamsUpdate;
}>;
type JazzRoomEventLocalParticipantChanged<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'localParticipantChanged';
  payload: {
    participant: JazzRoomParticipant<T>;
  };
}>;
type JazzRoomEventDominantSpeakerChanged = Readonly<{
  type: 'dominantSpeakerChanged';
  payload: {
    id: JazzRoomParticipantId;
    prevId: JazzRoomParticipantId | undefined;
  };
}>;
type JazzRoomEventDominantSpeakerLeft = Readonly<{
  type: 'dominantSpeakerLeft';
}>;
type JazzRoomEventDestroy = Readonly<{
  type: 'destroy';
}>;
type JazzRoomEventAccessByPermission = Readonly<{
  type: 'accessByPermission';
}>;
type JazzRoomEventStatusChanged<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'statusChanged';
  payload:
    | {
        status: JazzRoomStatusMap['CONNECTING'];
      }
    | {
        status: JazzRoomStatusMap['CONNECTED'];
        localParticipantId: JazzRoomParticipantId;
        roomId: JazzRoomId;
        meetingId: JazzMeetingId;
      }
    | {
        status: JazzRoomStatusMap['DISCONNECTING'];
      }
    | {
        status: JazzRoomStatusMap['DISCONNECTED'];
      }
    | {
        status: JazzRoomStatusMap['ERROR'];
        error: JazzRoomErrorReason<T>;
      };
}>;
type JazzRoomEventConnecting = Readonly<{
  type: 'connecting';
}>;
type JazzRoomEventConnected = Readonly<{
  type: 'connected';
  payload: {
    localParticipantId: JazzRoomParticipantId;
    roomId: JazzRoomId;
    meetingId: JazzMeetingId;
  };
}>;
type JazzRoomEventDisconnecting = Readonly<{
  type: 'disconnecting';
}>;
type JazzRoomEventDisconnected = Readonly<{
  type: 'disconnected';
}>;
type JazzRoomEventError<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  Readonly<{
    type: 'error';
    payload: {
      error: JazzRoomErrorReason<T>;
    };
  }>;
type JazzRoomEventConnectionChanged = Readonly<{
  type: 'connectionChanged';
  payload:
    | {
        status: JazzRoomConnectionStatusMap['FAILED'];
        reason: string;
      }
    | {
        status: JazzRoomConnectionStatusMap['CONNECTING'];
      }
    | {
        status: JazzRoomConnectionStatusMap['CONNECTED'];
      }
    | {
        status: JazzRoomConnectionStatusMap['DISCONNECTED'];
      };
}>;
type JazzRoomEventConnectionFailed = Readonly<{
  type: 'connectionFailed';
  payload: {
    reason: string;
  };
}>;
type JazzRoomEventConnectionConnecting = Readonly<{
  type: 'connectionConnecting';
}>;
type JazzRoomEventConnectionOpen = Readonly<{
  type: 'connectionOpen';
}>;
type JazzRoomEventConnectionDisconnected = Readonly<{
  type: 'connectionDisconnected';
}>;
type JazzRoomEventReconnecting = Readonly<{
  type: 'reconnecting';
  payload: {
    reason: JazzRoomReconnectingReason;
  };
}>;
type JazzRoomEventConnectionInterrupted = Readonly<{
  type: 'connectionInterrupted';
  payload: {
    reason: ConnectionInterruptedReason;
  };
}>;
type JazzRoomEventPermissionGranted<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'permissionGranted';
  payload: {
    permission: JazzRoomUserPermissionKey<T>;
  };
}>;
type JazzRoomEventPermissionDenied<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'permissionDenied';
  payload: {
    permission: JazzRoomUserPermissionKey<T>;
  };
}>;
type JazzRoomEventRolePermissionsChanged<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'rolePermissionsChanged';
  payload: {
    userRole: JazzRoomParticipantRole;
    permissions: JazzRoomPartialUserPermissions<T>;
    prevPermissions: JazzRoomPartialUserPermissions<T>;
  };
}>;
type JazzRoomEventPermissionRequested<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<{
  type: 'permissionRequested';
  payload: {
    participantId: JazzRoomParticipantId;
    permission: JazzRoomUserPermissionKey<T>;
  };
}>;
type JazzRoomEvent<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  | JazzRoomEventAddTrack
  | JazzRoomEventRemoveTrack
  | JazzRoomEventTrackMuteChanged
  | JazzRoomEventTrackMuteChangeRejected
  | JazzRoomEventTrackAddRejected
  | JazzRoomEventTrackUpdated
  | JazzRoomEventRemoteTrackInfo
  | JazzRoomEventSettingsChanged
  | JazzRoomEventLocalParticipantId
  | JazzRoomEventLocalParticipantChanged<T>
  | JazzRoomEventParticipants<T>
  | JazzRoomEventParticipantUpdate<T>
  | JazzRoomEventParticipantLeft<T>
  | JazzRoomEventParticipantJoined<T>
  | JazzRoomEventDominantSpeakerChanged
  | JazzRoomEventDominantSpeakerLeft
  | JazzRoomEventDestroy
  | JazzRoomEventAccessByPermission
  | JazzRoomEventParamsChanged
  | JazzRoomEventKicked
  | JazzRoomEventLeave
  | JazzRoomEventPermissionGranted<T>
  | JazzRoomEventPermissionDenied<T>
  | JazzRoomEventRolePermissionsChanged<T>
  | JazzRoomEventPermissionRequested<T>
  | JazzRoomEventStatusChanged<T>
  | JazzRoomEventConnecting
  | JazzRoomEventConnected
  | JazzRoomEventDisconnecting
  | JazzRoomEventDisconnected
  | JazzRoomEventError<T>
  | JazzRoomEventConnectionChanged
  | JazzRoomEventConnectionFailed
  | JazzRoomEventConnectionConnecting
  | JazzRoomEventConnectionOpen
  | JazzRoomEventConnectionDisconnected
  | JazzRoomEventReconnecting
  | JazzRoomEventConnectionInterrupted;
type JazzRoomEvents<T extends JazzRoomExtender[] = JazzRoomExtender[]> =
  EventToMap<JazzRoomEvent<T>>;
type JazzRoomSources = ReadonlyMap<MediaType, JazzRoomMediaSourceState>;
/**
 * @deprecated use JazzRoomId
 */
type JazzRoomConferenceId = string;
type JazzRoomId = string;
type JazzMeetingId = string;
type JazzRoomType = StringEnum<'MEETING'>;
type JazzRoomParams = Readonly<{
  roomId: JazzRoomId;
  roomPassword: string;
  /**
   * @deprecated use roomId
   */
  conferenceId: JazzRoomId;
  /**
   * @deprecated use roomPassword
   */
  conferencePassword: string;
  meetingId: QueryAtom<JazzMeetingId | undefined>;
  /**
   * @deprecated
   */
  meetingPassword: QueryAtom<string | undefined>;
  roomType: QueryAtom<JazzRoomType | undefined>;
  /**
   * @deprecated
   */
  nodeToken: QueryAtom<string | undefined>;
  /**
   * @deprecated
   */
  sessionSecret: QueryAtom<string | undefined>;
}>;
type JazzRoomUserPermissionRequests<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = ReadonlyMap<
  JazzRoomUserPermissionRequestKey<T>,
  JazzRoomUserPermissionRequest<T>
>;
type JazzRoomRolePermissions<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = Readonly<
  Record<JazzRoomParticipantRole, JazzRoomPartialUserPermissions<T>>
>;
type JazzRoomPermissionRequests<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = ReadonlyArray<JazzRoomPermissionRequest<T>>;
type JazzRoomPermissionRequestResolutions<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = ReadonlyMap<
  JazzRoomParticipantId,
  ReadonlyMap<
    JazzRoomUserPermissionRequestKey<T>,
    JazzRoomPermissionRequestResolution
  >
>;
type JazzRoomGrantedPermissions<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = ReadonlyMap<
  JazzRoomParticipantId,
  ReadonlySet<JazzRoomUserPermissionRequestKey<T>>
>;
type JazzRoom<T extends JazzRoomExtender[] = JazzRoomExtender[]> = Readonly<{
  container: Container;
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<JazzRoomEvent<T>>;
  on: TransportRoot<JazzRoomEvents<T>>['on'];
  once: TransportRoot<JazzRoomEvents<T>>['once'];
  off: TransportRoot<JazzRoomEvents<T>>['off'];
  status: QueryAtom<JazzRoomStatus>;
  error: QueryAtom<JazzRoomErrorReason<T> | undefined>;
  connectionStatus: QueryAtom<JazzRoomConnectionStatus>;
  params: JazzRoomParams;
  settings: JazzRoomSettingsQueries;
  ready: (
    status?: 'connected' | 'disconnecting' | 'disconnected',
  ) => Promise<void>;
  leave: (options?: { endConference: boolean }) => Promise<void>;
  localParticipant: QueryAtom<JazzRoomParticipant<T> | undefined>;
  remoteParticipants: QueryAtom<Readonly<JazzRoomParticipant<T>>[]>;
  participants: QueryAtom<Readonly<JazzRoomParticipant<T>>[]>;
  dominantParticipantId: QueryAtom<JazzRoomParticipantId | undefined>;
  sources: QueryAtom<RoomMediaSourcesState>;
  getSources: () => RoomMediaSourcesState;
  userPermissions: QueryAtom<JazzRoomUserPermissions<T>>;
  userPermissionRequests: QueryAtom<JazzRoomUserPermissionRequests<T>>;
  requestPermission: (permission: JazzRoomUserPermissionKey<T>) => void;
  /** @deprecated use getParticipantMediaSource */
  getParticipantSource: (
    participantId: JazzRoomParticipantId,
    mediaType: MediaType,
  ) => RoomMediaSourceStateBase | undefined;
  getParticipantMediaSource: (
    participantId: JazzRoomParticipantId,
    source: MediaType,
  ) => RoomMediaSourcesGettingMediaSource;
  userAudioStream: QueryAtom<MediaStream | undefined>;
  userVideoStream: QueryAtom<MediaStream | undefined>;
  displayStream: QueryAtom<MediaStream | undefined>;
  setUserAudioInput: (stream: MediaStream | undefined) => void;
  setUserVideoInput: (stream: MediaStream | undefined) => void;
  setDisplayVideoInput: (stream: MediaStream | undefined) => void;
  isAudioInputMuted: QueryAtom<boolean>;
  muteAudioInput: (isMuted: boolean) => Promise<void>;
  isVideoInputMuted: QueryAtom<boolean>;
  muteVideoInput: (isMuted: boolean) => Promise<void>;
  isDisplayVideoInputMuted: QueryAtom<boolean>;
  muteDisplayVideoInput: (isMuted: boolean) => Promise<void>;
  displayCaptureMode: Atom<DisplayCaptureMode>;
  setDisplayCaptureMode: (mode: DisplayCaptureMode) => void;
  /** @deprecated use getParticipantMediaSource */
  getAudioStream: (
    participantId: JazzRoomParticipantId,
  ) => MediaStream | undefined;
  /** @deprecated use getParticipantMediaSource */
  getVideoStream: (
    participantId: JazzRoomParticipantId,
    request: {
      source: JazzRoomVideoSource;
    },
  ) => MediaStream | undefined;
  getVideoStreamSourceName: (
    participantId: JazzRoomParticipantId,
    source: JazzRoomVideoSource,
  ) => string | undefined;
  moderator: {
    permissionRequests: QueryAtom<JazzRoomPermissionRequests<T>>;
    rolePermissions: QueryAtom<JazzRoomRolePermissions<T>>;
    permissionRequestResolutions: QueryAtom<
      JazzRoomPermissionRequestResolutions<T>
    >;
    grantedPermissions: QueryAtom<JazzRoomGrantedPermissions<T>>;
    muteUsers: (
      participantIds:
        | ReadonlyArray<JazzRoomParticipantId>
        | JazzRoomParticipantId,
      type: RoomMuteMediaType,
    ) => void;
    muteUsersAll: (type: RoomMuteMediaType) => void;
    kickUsers: (
      participantIds:
        | ReadonlyArray<JazzRoomParticipantId>
        | JazzRoomParticipantId,
    ) => void;
    kickUsersAll: () => void;
    setRolePermissions: (props: {
      role: JazzRoomParticipantRole;
      permissions: JazzRoomPartialUserPermissions<T>;
    }) => Promise<void>;
    grantPermission: (
      participantId: JazzRoomParticipantId,
      permission: JazzRoomUserPermissionRequestKey<T>,
      allowed: boolean,
    ) => void;
    removeGrantedPermission: (
      permission: JazzRoomUserPermissionRequestKey<T>,
    ) => void;
    setSettings: (settingsUpdate: JazzRoomSettingsUpdate) => Promise<void>;
  };
  extend: <T extends JazzRoomExtender[] = JazzRoomExtender[]>() => JazzRoom<T>;
}>;
type JazzRoomPermissionRequest<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = {
  participantId: JazzRoomParticipantId;
  created: Timestamp;
  permissionKey: JazzRoomUserPermissionRequestKey<T>;
};
type JazzRoomPermissionRequestResolution<
  T extends JazzRoomExtender[] = JazzRoomExtender[],
> = {
  participantId: JazzRoomParticipantId;
  created: Timestamp;
  permissionKey: JazzRoomUserPermissionRequestKey<T>;
  resolution: boolean;
};

type JazzClientExtender = {
  userInfo: Record<string, unknown>;
};

type BaseExtender<ResponseData = unknown> =
  | BaseRequestAdapter<ResponseData>
  | BaseResponseAdapter<ResponseData>;
type BaseRequestAdapter<ResponseData = unknown> = {
  requestAdapter: (baseRequest: any) => unknown;
  responseAdapter?: (data: any) => ResponseData;
};
type BaseResponseAdapter<ResponseData = unknown> = {
  requestAdapter?: (baseRequest: any) => unknown;
  responseAdapter: (data: any) => ResponseData;
};
type ValidExtender<E> = E extends false | undefined ? never : E;
type Extender<ResponseData = unknown> =
  | BaseExtender<ResponseData>
  | undefined
  | false;
type ResponseExtender<
  ResponseData,
  Ext extends Extender | Extender[] | [] = Extender,
> = Ext extends Extender[]
  ? ResponseExtenderMultiple<ResponseData, Ext>
  : ValidExtender<Ext> extends BaseExtender
    ? ResponseExtenderSingle<ResponseData, ValidExtender<Ext>>
    : ResponseData;
type ResponseExtenderSingle<T, R extends BaseExtender> =
  R extends BaseExtender<infer S> ? (S extends void ? T : DeepUnion<T, S>) : T;
type ResponseExtenderMultiple<T, Exts extends Extender[]> = Exts extends [
  infer First,
  ...infer Rest,
]
  ? ValidExtender<First> extends BaseExtender
    ? Rest extends Extender[]
      ? ResponseExtenderMultiple<
          ResponseExtenderSingle<T, ValidExtender<First>>,
          Rest
        >
      : T
    : Rest extends Extender[]
      ? ResponseExtenderMultiple<T, Rest>
      : T
  : T;
type DeepUnion<T, U> = DeepUnion$1<T, U>;
type DeepUnionAll<T extends unknown[]> = DeepUnionAll$1<T>;
/**
 * Проверяет, является ли переданное значение валидным экстендером.
 *
 * @param extender - Значение для проверки.
 */
declare function isExtender<ResponseData = unknown>(
  extender: unknown,
): extender is Extender<ResponseData>;

type MeetingRole = StringEnum<'OWNER' | 'MEMBER'>;
type GetMeetingHistoryListParams = {
  offset?: number;
  limit?: number;
};
type ApiMeetingHistoryResult = {
  /**
   * Уникальный id встречи, записанной в истории
   */
  meetingId: JazzMeetingId;
  /**
   * id комнаты для подключения в данном домене (может быть не уникальным среди разных доменов)
   */
  roomId: JazzRoomId;
  meetingStartedAt?: UTCDate | null;
  meetingStoppedAt?: UTCDate | null;
  role: MeetingRole;
  roomType?: JazzRoomType;
  userRoomPassword: string;
  roomOwnerName?: string;
  userName?: string;
  meetingTitle: string;
  otherParticipants?: Array<{
    name: string;
  }>;
  filesInfo?: Array<{
    type: string;
    status: 'READY' | 'NOT_READY' | 'ERROR' | 'PROCESSING';
  }>;
  isNetworkRestrictTranscription?: boolean;
  summarizationEnabled?: boolean;
};
type MeetingHistory = Omit<ApiMeetingHistoryResult, 'role'> & {
  role: JazzRoomParticipantRole;
};
type ApiMeetingHistoryListItem = {
  /**
   * Уникальный id встречи, записанной в истории
   */
  meetingId: JazzMeetingId;
  /**
   * id комнаты для подключения в данном домене (может быть не уникальным среди разных доменов)
   */
  roomId: JazzRoomId;
  /**
   * Присылает domain на котором была создана встреча
   */
  meetingStartedAt?: UTCDate | null;
  meetingStoppedAt?: UTCDate | null;
  role: MeetingRole;
  roomType?: JazzRoomType;
  userRoomPassword: string;
  roomOwnerName?: string;
  meetingTitle: string;
  domain: string;
};
type MeetingHistoryListItem = Omit<ApiMeetingHistoryListItem, 'role'> & {
  role: JazzRoomParticipantRole;
};
type MeetingHistoryListResult = {
  meetings: Array<MeetingHistoryListItem>;
};

type CreateMeetingRequest = {
  title: string;
  guestEnabled?: boolean;
  lobbyEnabled?: boolean;
};
type CreateMeetingResponse = {
  roomId: string;
  password: string;
  domain: string;
  url: string;
  isRussianCACertificateRequired: boolean;
};

/**
 * Manager of conferences
 */
type JazzSdkConferenceManager = Readonly<{
  /**
   * Connects to a conference room
   */
  join: <Ext extends Extender[]>(
    params: JazzClientJoinParams,
    ...extenders: Ext
  ) => JazzRoom;
  /**
   * Gets details about a conference
   */
  getDetails: <Ext extends Extender[]>(
    params: JazzSdkRoomDetailsParams,
    ...extenders: Ext
  ) => Promise<ResponseExtender<JazzSdkConferenceRoomDetails, Ext>>;
  /**
   * Creates a conference for authorised users.
   *
   * Use the "guestEnabled" parameter to allow anonymous participants
   * to join the conference.
   */
  createRoom: <Ext extends Extender[]>(
    params: JazzSdkCreateRoomRequest,
    ...extenders: Ext
  ) => Promise<ResponseExtender<JazzSdkCreateRoomResponse, Ext>>;
  /**
   * Updates the conference settings.
   */
  update: <Ext extends Extender[]>(
    params: JazzClientUpdateParams,
    ...extenders: Ext
  ) => Promise<void>;
  /**
   * Closes the conference to connect.
   */
  close: (params: JazzClientCloseParams) => Promise<void>;
  /**
   * Gets conference history details.
   */
  getHistoryDetails: <Ext extends Extender[]>(
    id: string,
    ...extenders: Ext
  ) => Promise<ResponseExtender<MeetingHistory, Ext>>;
  /**
   * Gets conference history list.
   */
  getMeetingHistoryList: <Ext extends Extender[]>(
    params: GetMeetingHistoryListParams,
    ...extenders: Ext
  ) => Promise<ResponseExtender<MeetingHistoryListResult, Ext>>;
}>;
type JazzClientCloseParams = {
  /**
   * @deprecated use roomId
   */
  conferenceId?: string;
  roomId: string;
  password: string;
};
type JazzClientJoinParams = {
  /**
   * @deprecated use roomId
   */
  conferenceId?: string;
  roomId: string;
  password: string;
};
type JazzClientUpdateParams = {
  /**
   * @deprecated use roomId
   */
  conferenceId?: string;
  roomId: string;
  password: string;
  settings: {
    title?: string;
    lobbyEnabled?: boolean;
  };
};
type JazzSdkRoomDetails = Readonly<{
  roomType: StringEnum<'MEETING'>;
  roomTitle?: string;
}>;
type JazzSdkGetRoomDetailsError =
  | {
      type: 'notFound';
    }
  | {
      type: 'unauthorised';
    }
  | {
      type: 'unknown';
    }
  | {
      type: 'accessDenied';
    }
  | {
      type: 'httpClientError';
    };
type JazzSdkConferenceRoomDetails = JazzSdkRoomDetails;
type JazzSdkCreateAnonymousRoomParams = Readonly<{
  title: string;
}>;
type JazzSdkCreateAnonymousRoomError = {
  type: 'unknown';
};
type JazzSdkCreateAnonymousRoomDetails = Readonly<{
  id: string;
  roomTitle: string;
  roomType: StringEnum<'ANONYMOUS'>;
  password: string;
  url: string;
}>;
type JazzSdkCreateAnonymousRoomResult = JazzSdkCreateAnonymousRoomDetails;
type JazzSdkCreateConferenceParams = Readonly<{
  title: string;
  isGuestEnabled?: boolean;
  isLobbyEnabled?: boolean;
  jazzNextOnly?: boolean;
  roomType?: JazzRoomType;
}>;
type JazzSdkCreateConferenceError = {
  type: 'unknown';
};
type JazzSdkCreateConferenceDetails = Readonly<{
  id: string;
  roomTitle: string;
  roomType: JazzRoomType;
  password: string;
}>;
type JazzSdkCreateConferenceResult = JazzSdkCreateConferenceDetails;
type JazzSdkRoomDetailsParams = Readonly<{
  /**
   * @deprecated use roomId
   */
  conferenceId?: string;
  roomId: string;
  password: string;
}>;
type JazzSdkCreateRoomRequest = CreateMeetingRequest;
type JazzSdkCreateRoomResponse = CreateMeetingResponse;

type AuthStatus = 'anonymous' | 'authorised';
type AuthMethod = StringEnum<'token'>;

type JazzSdkUserInfoAuthType = StringEnum<'SDK' | 'ANONYMOUS'>;
type JazzSdkAuthStatus = 'authorised' | 'anonymous' | 'pending';
type JazzSdkAuthMethod = AuthMethod;
type JazzSdkUserInfoAuthError =
  | 'OK'
  | 'AUTH_TYPE_MISMATCH'
  | 'TOKEN_EXPIRED'
  | 'TOKEN_INVALID'
  | 'TOKEN_MISSING';
type AuthorisedEvent<T extends JazzClientExtender[] = JazzClientExtender[]> = {
  type: 'authorised';
  payload: Readonly<{
    authMethod: AuthMethod;
    userInfo: JazzSdkUserInfo<T>;
  }>;
};
type LoginStartedEvent = {
  type: 'loginStarted';
  payload: Readonly<{
    authMethod: AuthMethod;
  }>;
};
type LoginFailedEvent = {
  type: 'loginFailed';
  payload: Readonly<{
    authMethod: AuthMethod;
  }>;
};
type LoggedOutEvent<T extends JazzClientExtender[] = JazzClientExtender[]> = {
  type: 'loggedOut';
  payload: Readonly<{
    authMethod?: AuthMethod;
    authStatus: AuthStatus;
    userInfo?: JazzSdkUserInfo<T>;
  }>;
};
type InvalidTokenEvent = {
  type: 'invalidToken';
};
type UnauthorisedErrorEvent = {
  type: 'unauthorisedError';
};
type JazzSdkAuthEvent<T extends JazzClientExtender[] = JazzClientExtender[]> =
  | AuthorisedEvent<T>
  | LoginStartedEvent
  | LoginFailedEvent
  | LoggedOutEvent<T>
  | InvalidTokenEvent
  | UnauthorisedErrorEvent;
type JazzClientAuthEvents<
  T extends JazzClientExtender[] = JazzClientExtender[],
> = EventToMap<JazzSdkAuthEvent<T>>;
type JazzSdkUserInfoServerFeatures<
  T extends JazzClientExtender[] = JazzClientExtender[],
> = Readonly<{
  maxConferenceDuration: number | undefined;
  maxConferenceCapacity: number | undefined;
  maxUsersForInfiniteConference: number | undefined;
  lobbyAvailable: boolean;
  meetingHistoryAvailable: boolean;
  /**
   * Доступ к созданию комнат с гостями
   */
  privateRoomAvailable: boolean;
}> &
  TakeProperty<PropertyExtender<T, 'userInfo', 'intersection'>, 'features'>;
type JazzSdkUserInfo<T extends JazzClientExtender[] = JazzClientExtender[]> =
  | {
      authType: JazzSdkUserInfoAuthType;
      authErr: Exclude<JazzSdkUserInfoAuthError, 'OK'>;
      name?: string;
      email?: string;
      features?: Partial<JazzSdkUserInfoServerFeatures<T>>;
    }
  | ({
      authType: JazzSdkUserInfoAuthType;
      authErr: OnlyIfExists<JazzSdkUserInfoAuthError, 'OK'>;
      name?: string;
      email?: string;
      features: JazzSdkUserInfoServerFeatures<T>;
    } & Omit<PropertyExtender<T, 'userInfo'>, 'features'>);
/**
 * Jazz SDK authorisation service
 */
type JazzSdkAuthService<T extends JazzClientExtender[] = JazzClientExtender[]> =
  Readonly<{
    /** Authorisation event bus
     * @deprecated use on, off, once
     */
    event$: Observable<JazzSdkAuthEvent<T>>;
    /** Authorisation status */
    authStatus: QueryAtom<JazzSdkAuthStatus>;
    /** Authorisation method */
    authMethod: QueryAtom<JazzSdkAuthMethod | undefined>;
    /** Authorised user flag */
    isAuthorised: QueryAtom<boolean>;
    /**
     * Info about the current user.
     * Data can be retrieved for both authorised and anonymous users.
     */
    userInfo: QueryAtom<JazzSdkUserInfo<T> | undefined>;
    /**
     * Authenticates by an SDK token
     *
     * @return JazzSdkUserInfo if a user is authorised
     */
    loginBySdkToken: (sdkToken: string) => Promise<JazzSdkUserInfo<T>>;
    /**
     * Authenticates by a low-level auth-token
     *
     * @return `true` if a user is authorised
     */
    setAuthToken: (authToken: string) => Promise<boolean>;
    /** Discards a current user session */
    logout: () => Promise<void>;
    on: TransportRoot<JazzClientAuthEvents<T>>['on'];
    once: TransportRoot<JazzClientAuthEvents<T>>['once'];
    off: TransportRoot<JazzClientAuthEvents<T>>['off'];
  }>;

type JazzClientEventAddRoomConnection = {
  type: 'addRoomConnection';
  payload: {
    roomConnection: JazzRoomConnection;
  };
};
type JazzClientEventRemoveRoomConnection = {
  type: 'removeRoomConnection';
  payload: {
    roomConnection: JazzRoomConnection;
  };
};
type JazzClientEventAddRoom = {
  type: 'addRoom';
  payload: {
    room: JazzRoom;
  };
};
type JazzClientEventRemoveRoom = {
  type: 'removeRoom';
  payload: {
    room: JazzRoom;
  };
};
type JazzClientEventDestroy = {
  type: 'destroy';
};
type JazzClientEvent =
  | JazzClientEventAddRoom
  | JazzClientEventRemoveRoom
  | JazzClientEventDestroy
  | JazzClientEventAddRoomConnection
  | JazzClientEventRemoveRoomConnection;
type JazzClientEvents = EventToMap<JazzClientEvent>;
/**
 * JazzClient is a client for the Jazz server
 */
type JazzClient<T extends JazzClientExtender[] = JazzClientExtender[]> =
  Readonly<{
    container: Container;
    /** Server URL which is used by the client */
    serverUrl: string;
    /** Authorization service to manage a user session */
    auth: JazzSdkAuthService<T>;
    /** Manager of conferences */
    conferences: JazzSdkConferenceManager;
    /**
     * @deprecated use on, off, once
     */
    event$: Observable<JazzClientEvent>;
    on: TransportRoot<JazzClientEvents>['on'];
    once: TransportRoot<JazzClientEvents>['once'];
    off: TransportRoot<JazzClientEvents>['off'];
    extend: <
      T extends JazzClientExtender[] = JazzClientExtender[],
    >() => JazzClient<T>;
    destroy: () => void;
  }>;
/** Options for `createJazzClient()` factory */
type JazzClientOptions = Readonly<{
  /**
   * Jazz server URL
   */
  serverUrl: string;
  /**
   * Provider for working with authorization
   */
  authProvider?: JazzSdkAuthProvider;
}>;
type JazzSdkAuthProvider = {
  /**
   * 401 error handler
   */
  handleUnauthorizedError?: (
    context: JazzSdkAuthService,
  ) => Promise<ApiAuthErrorResolution>;
  /**
   * 403 error handler
   */
  handleAuthorizationInvalidError?: (
    context: JazzSdkAuthService,
  ) => Promise<ApiAuthErrorResolution>;
};

type RoomConnectionEvent =
  | JazzRoomEventConnectionChanged
  | JazzRoomEventConnectionFailed
  | JazzRoomEventConnectionConnecting
  | JazzRoomEventConnectionOpen
  | JazzRoomEventConnectionDisconnected
  | JazzRoomEventConnectionInterrupted
  | JazzRoomEventReconnecting
  | JazzRoomEventConnecting
  | JazzRoomEventAddRoom
  | JazzRoomEventRemoveRoom
  | JazzRoomEventError;
type RoomConnectionEvents = EventToMap<RoomConnectionEvent>;
type JazzRoomEventAddRoom = {
  type: 'addRoom';
  payload: {
    roomConnection: JazzRoomConnection;
    room: JazzRoom;
  };
};
type JazzRoomEventRemoveRoom = {
  type: 'removeRoom';
  payload: {
    roomConnection: JazzRoomConnection;
    room: JazzRoom;
  };
};
type JazzRoomConnection = {
  roomId: JazzRoomId;
  roomPassword: string;
  connectionStatus: QueryAtom<JazzRoomConnectionStatus>;
  container: Container;
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<RoomConnectionEvent>;
  on: TransportRoot<RoomConnectionEvents>['on'];
  once: TransportRoot<RoomConnectionEvents>['once'];
  off: TransportRoot<RoomConnectionEvents>['off'];
};

declare class OrderDisplayTrackError extends Error {
  constructor();
}

type MediaKind$2 = 'audio' | 'video' | 'desktop';
declare class RequiredDeviceIdError extends Error {
  kind: MediaKind$2;
  constructor(kind: MediaKind$2);
}

declare class ScreenShareUserCanceledError extends Error {
  constructor();
}

declare class NotReadableError extends Error {
  constructor();
}

declare class DisplayPermissionDeniedError extends Error {
  constructor();
}

type CollectMetricsMetaActions$1 = {
  set: (key: string, value: string) => void;
  get: (key: string) => string | undefined;
  delete: (key: string) => void;
  clear: () => void;
};

type CollectMetricsMetaActions = CollectMetricsMetaActions$1;
type CollectMetricsMeta = Record<string, string> & {
  custom_data?: Record<string, string>;
};
type CollectMetricsMetricData = {
  name: string;
  value?: string | number;
  /**
   * Если метрика состоит из нескольких свойств,
   * можно их передать через label
   */
  labels?: Record<string, string | number | boolean>;
};
type CollectMetricsMetric = Readonly<{
  type: string;
  date?: number;
  values?: CollectMetricsMetricData[];
  meta?: CollectMetricsMeta;
}>;
type CollectMetricsHandler = (metric: CollectMetricsMetric) => void;

type DisplayInputOptions = {
  /**
   * Create media stream from device
   */
  device?: LocalVideoInputDevice;
};
type AudioInputOptions = {
  device: LocalAudioInputDevice;
  isMuted?: boolean;
};
type VideoInputOptions = {
  device: LocalVideoInputDevice;
  isMuted?: boolean;
  resolution?: JazzVideoResolution;
  frameRate?: number;
};
type GetSelectedAudioInputOptions = {
  isMuted?: boolean;
};
type GetSelectedVideoInputOptions = {
  isMuted?: boolean;
  resolution?: JazzVideoResolution;
  frameRate?: number;
};

type MediaKind$1 = 'audio' | 'video';
declare class UserDeniedPermissionError extends Error {
  constructor(types: MediaKind$1[]);
}
declare class DevicesNotFoundError extends Error {
  kind: MediaKind$1;
  constructor(kind: MediaKind$1);
}

/**
 * Jazz SDK Plugin provides additional features.
 */
type JazzSdkPlugin<T extends Module<AnyObject> = Module<AnyObject>> = Promise<
  () => {
    key: string | undefined;
    module: JazzSdkModuleDeclaration<T>;
  }
>;
type JazzSdkModuleDeclaration<
  T extends JazzSdkModule<AnyObject> = JazzSdkModule<AnyObject>,
> = ModuleDeclaration<T>;
type JazzSdkModule<T extends AnyObject = AnyObject> = Module<T>;
type JazzSdkAdditionalPlugins = ReadonlyArray<JazzSdkPlugin>;
type EmptyObject = {
  [K in string]: never;
};
type ValuesProps = AnyObject;
type JazzSdkModuleFactoryProps<
  Props extends ValuesProps | EmptyObject | undefined,
  Name extends string | undefined = undefined,
> = (Props extends undefined | EmptyObject
  ? {
      container: Container;
      scope: Scope;
    }
  : {
      container: Container;
      deps: Props;
      scope: Scope;
    }) &
  (Name extends undefined
    ? {}
    : {
        name: Name;
      });
type JazzSdkModuleFactory<
  T extends Module<ValuesProps>,
  Deps extends ValuesProps | EmptyObject | undefined,
  Name extends string | undefined,
> = (props: JazzSdkModuleFactoryProps<Deps, Name>) => T;

type JazzSdkEventAddClient = Readonly<{
  type: 'addClient';
  payload: {
    client: JazzClient;
  };
}>;
type JazzSdkEventRemoveClient = Readonly<{
  type: 'removeClient';
  payload: {
    client: JazzClient;
  };
}>;
type JazzSdkEventAddRoom = Readonly<{
  type: 'addRoom';
  payload: {
    client: JazzClient;
    roomConnection: JazzRoomConnection;
    room: JazzRoom;
  };
}>;
type JazzSdkEventRemoveRoom = Readonly<{
  type: 'removeRoom';
  payload: {
    client: JazzClient;
    roomConnection: JazzRoomConnection;
    room: JazzRoom;
  };
}>;
type JazzSdkEventAddRoomConnection = Readonly<{
  type: 'addRoomConnection';
  payload: {
    client: JazzClient;
    roomConnection: JazzRoomConnection;
  };
}>;
type JazzSdkEventRemoveRoomConnection = Readonly<{
  type: 'removeRoomConnection';
  payload: {
    client: JazzClient;
    roomConnection: JazzRoomConnection;
  };
}>;
type JazzSdkEvent =
  | JazzSdkEventAddClient
  | JazzSdkEventRemoveClient
  | JazzSdkEventAddRoom
  | JazzSdkEventRemoveRoom
  | JazzSdkEventAddRoomConnection
  | JazzSdkEventRemoveRoomConnection;
type JazzSdkEvents = EventToMap<JazzSdkEvent>;
/**
 * Jazz SDK provides a common runtime for Jazz Clients and Plugins
 */
type JazzSdk = Controller<{
  container: Container;
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<JazzSdkEvent>;
  on: TransportRoot<JazzSdkEvents>['on'];
  once: TransportRoot<JazzSdkEvents>['once'];
  off: TransportRoot<JazzSdkEvents>['off'];
}>;
type JazzSdkOptions = Readonly<{
  /** Extensions for the SDK */
  plugins?: JazzSdkAdditionalPlugins;
  /**
   * Custom ID to identify an application which uses the SDK.
   *
   * @deprecated use clientName
   */
  userAgent?: string;
  /**
   * Custom ID to identify an application which uses the SDK.
   * It used in meta information when transmitting metrics.
   */
  clientName?: string;
  /**
   * The user's custom session ID.
   * It is used to identify the browser or application that the user is using.
   */
  clientId?: string;
  /**
   * Custom storage for persisting data between sessions.
   * By default, a platform-specific storage is used.
   * Pass 'in-memory' value to force using an in-memory storage.
   */
  localStorage?: KeyValueStorage | 'in-memory';
  /**
   * Custom storage to persist data during a user session.
   * By default, a platform-specific storage is used.
   * Pass 'in-memory' value to force using an in-memory storage.
   */
  sessionStorage?: KeyValueStorage | 'in-memory';
  /**
   * Custom DI container for low-level SDK setup.
   */
  container?: Container;
  /**
   * Key-value flags to low-level SDK setup.
   */
  configFlags?: Readonly<Record<string, string>>;
  /**
   * Initial audio input deviceId
   */
  audioInputDeviceId?: string | undefined;
  /**
   * Initial audio output deviceId
   */
  audioOutputDeviceId?: string | undefined;
  /**
   * Initial video input deviceId
   */
  videoInputDeviceId?: string | undefined;
  /**
   * Mod of the audio input switching strategy.
   * - 'new-prefer' - automatic selection of the added device
   * - 'manual' - the device does not switch when adding a new device
   * @default 'new-prefer'
   */
  audioInputSwitchingMode?: SwitchingMode;
  /**
   * Mod of the audio output switching strategy.
   * - 'new-prefer' - automatic selection of the added device
   * - 'manual' - the device does not switch when adding a new device
   * @default 'new-prefer'
   */
  audioOutputSwitchingMode?: SwitchingMode;
  /**
   * Mod of the video input switching strategy.
   * - 'new-prefer' - automatic selection of the added device
   * - 'manual' - the device does not switch when adding a new device
   * @default 'new-prefer'
   */
  videoInputSwitchingMode?: SwitchingMode;
}>;
type SwitchingMode = 'new-prefer' | 'manual';

declare function createJazzClient(
  sdk: JazzSdk | JazzClient,
  options: JazzClientOptions,
): Promise<JazzClient>;

type SdkTokenOptions = {
  /**
   * Уникальный идентификатор запроса от клиента к серверу
   * @example beaff5c1-644c-413f-ba76-a583d892b5a4
   */
  requestId?: string;
  /**
   * Время в секундах через которое истечет срок жизни токена
   * @default 120
   */
  expireIn?: number;
  /**
   * Название компании или проекта используется в логах
   * Есть ограничение в 100 символов
   */
  iss?: string;
  /**
   * Идентификатор пользователя
   */
  sub: string;
  /**
   * Имя пользователя
   */
  userName?: string;
  /**
   * Почта пользователя
   */
  userEmail?: string;
};

/**
 *
 * @param secret base64 строка
 * @param options настройки окружения
 *
 * @returns {Promise} токен доступа
 */
declare function createSdkToken(
  secret: string,
  options: SdkTokenOptions,
): Promise<{
  sdkToken: string;
}>;

declare const withAnonymousJoin: (params: { userName: string }) => Extender;
declare const withAnonymousCreateRoom: () => Extender;

/**
 * Warm up initial instance
 */
type JoinWarmUp = Readonly<{
  /**
   * Connects to a conference room
   */
  join: <Ext extends Extender[]>(
    params: JazzClientJoinWarmUpParams,
    ...extenders: Ext
  ) => JazzRoomWarmUp;
}>;
type JazzRoomWarmUp = {
  /**
   * Status of warm up mode enabled
   */
  isEnabled: Atom<boolean>;
  room: JazzRoom;
  join: () => Promise<void>;
  cancel: () => Promise<void>;
};
type JazzClientJoinWarmUpParams = {
  roomId: string;
  password: string;
};

declare function getJoinWarmUp(jazzClient: JazzClient): JoinWarmUp;

/**
 * The IncorrectServerUrlError class is intended for creating and handling a specific error
 * that occurs when an invalid value is assigned to serverUrl.
 */
declare class IncorrectServerUrlError extends Error {
  constructor();
}

declare function getJazzClient<R extends JazzRoomExtender[]>(
  jazzRoom: JazzRoom<R>,
): JazzClient;

type RoomMuteMediaType = 'audio' | 'video';

type MediaKind = 'audio' | 'video' | 'media';
declare class DeniedBySystemError extends Error {
  kind: MediaKind;
  constructor(audio: boolean, video: boolean);
}

type LocalDevicesEventAddTrack = Readonly<{
  type: 'addTrack';
  payload: {
    stream: MediaStream;
    mediaType: MediaType$1;
    isMuted: boolean;
  };
}>;
type LocalDevicesEventRemoveTrack = Readonly<{
  type: 'removeTrack';
  payload: {
    stream: MediaStream;
    mediaType: MediaType$1;
  };
}>;
type LocalDevicesEventDisposeTrack = Readonly<{
  type: 'disposeTrack';
  payload: {
    stream: MediaStream;
    mediaType: MediaType$1;
  };
}>;
type LocalDevicesEventMuteTrackChanged = Readonly<{
  type: 'muteTrackChanged';
  payload: {
    stream: MediaStream;
    mediaType: MediaType$1;
    isMuted: boolean;
  };
}>;
type LocalDevicesEventLocalTrackUpdated = Readonly<{
  type: 'localTrackUpdated';
  payload: {
    stream: MediaStream;
    mediaType: MediaType$1;
    isMuted: boolean;
  };
}>;
type LocalDevicesEventMixDisplayAudio = Readonly<{
  type: 'mixDisplayAudio';
  payload: {
    enabled: boolean;
    stream: MediaStream;
  };
}>;
type LocalDevicesEventAudioAGCChanged = Readonly<{
  type: 'audioAGCChanged';
  payload: {
    isEnabled: boolean;
  };
}>;
type LocalDevicesEventAudioInputChanged = Readonly<{
  type: 'audioInputChanged';
  payload: {
    device: LocalAudioInputDevice;
    prevDevice: LocalAudioInputDevice | undefined;
  };
}>;
type LocalDevicesEventVideoInputChanged = Readonly<{
  type: 'videoInputChanged';
  payload: {
    device: LocalVideoInputDevice;
    prevDevice: LocalVideoInputDevice | undefined;
  };
}>;
type LocalDevicesEventAudioOutputChanged = Readonly<{
  type: 'audioOutputChanged';
  payload: {
    device: LocalAudioOutputDevice;
    prevDevice: LocalAudioOutputDevice | undefined;
  };
}>;
type LocalDevicesEventMediaDevicesChanged = Readonly<{
  type: 'mediaDevicesChanged';
  payload: {
    devices: ReadonlyArray<LocalMediaDevice>;
    groupedDevices: GroupedDevices;
    added: ReadonlyArray<LocalMediaDevice>;
    removed: ReadonlyArray<LocalMediaDevice>;
    groupedAddedDevices: GroupedDevices;
    groupedRemovedDevices: GroupedDevices;
  };
}>;
type LocalDevicesEventPermissionsChanged = Readonly<{
  type: 'permissionsChanged';
  payload: UserMediaPermissionState;
}>;
type LocalDevicesEventErrorDevicePermissions = Readonly<{
  type: 'errorDevicePermissions';
  payload: {
    type: MediaPermissionErrorType;
    kind: MediaPermissionErrorKind[];
    message: string;
  };
}>;
type LocalDevicesEventRequestDevicePermissions = {
  type: 'requestDevicePermissions';
  payload: {
    mediaTypes: UserMediaType$1[];
  };
};
type LocalDevicesEventSuccessDevicePermissions = {
  type: 'successDevicePermissions';
  payload: {
    mediaTypes: UserMediaType$1[];
    state: UserMediaPermissionState;
  };
};
type LocalDevicesEvent =
  | LocalDevicesEventAddTrack
  | LocalDevicesEventRemoveTrack
  | LocalDevicesEventDisposeTrack
  | LocalDevicesEventMuteTrackChanged
  | LocalDevicesEventLocalTrackUpdated
  | LocalDevicesEventMixDisplayAudio
  | LocalDevicesEventAudioAGCChanged
  | LocalDevicesEventAudioAGCChanged
  | LocalDevicesEventAudioInputChanged
  | LocalDevicesEventVideoInputChanged
  | LocalDevicesEventAudioOutputChanged
  | LocalDevicesEventMediaDevicesChanged
  | LocalDevicesEventPermissionsChanged
  | LocalDevicesEventErrorDevicePermissions
  | LocalDevicesEventRequestDevicePermissions
  | LocalDevicesEventSuccessDevicePermissions;
type LocalDevicesEvents = EventToMap<LocalDevicesEvent>;
type LocalDevicesMediaStreamState = {
  isMuted: QueryAtom<boolean>;
  mute: (isMuted: boolean) => Promise<void>;
  deviceId: string | undefined;
  mediaType: MediaType$1;
};
/**
 * Managed of local media devices.
 */
type LocalDevicesManager = {
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<LocalDevicesEvent>;
  on: TransportRoot<LocalDevicesEvents>['on'];
  once: TransportRoot<LocalDevicesEvents>['once'];
  off: TransportRoot<LocalDevicesEvents>['off'];
  /** Checking support for display media */
  /** Permissions for user media devices */
  userMediaPermissions: QueryAtom<UserMediaPermissionState>;
  /** Permissions for display media devices */
  /** Request a permission to use user media devices */
  requestUserMediaPermissions: (
    ...types: UserMediaType$1[]
  ) => Promise<UserMediaPermissionState>;
  /** Request a permission to use display media devices */
  /** Available audio inputs */
  audioInputDevices: QueryAtom<ReadonlyArray<LocalAudioInputDevice>>;
  /** Available audio outputs */
  audioOutputDevices: QueryAtom<ReadonlyArray<LocalAudioOutputDevice>>;
  /** Available video inputs */
  videoInputDevices: QueryAtom<ReadonlyArray<LocalVideoInputDevice>>;
  /** Current audio input for general use in conferences. */
  audioInput: QueryAtom<LocalAudioInputDevice | undefined>;
  /** Current audio output for general use in conferences. */
  audioOutput: QueryAtom<LocalAudioOutputDevice | undefined>;
  /** Current video input for general use in conferences. */
  videoInput: QueryAtom<LocalVideoInputDevice | undefined>;
  /** Selects the current audio input.
   *
   * @example
   * ```ts
   *  try {
   *   selectAudioInput(device)
   *  } catch(e) {
   *   if (e instanceof UserDeniedPermissionError) {
   *
   *   }
   *   if (e instanceof DevicesNotFoundError) {
   *
   *   }
   *  }
   * ```
   */
  selectAudioInput: (device: LocalAudioInputDevice) => Promise<void>;
  /** Selects the current audio output.
   *
   * @example
   * ```ts
   *  try {
   *   selectAudioOutput(device)
   *  } catch(e) {
   *   if (e instanceof DevicesNotFoundError) {
   *
   *   }
   *  }
   * ```
   */
  selectAudioOutput: (device: LocalAudioOutputDevice) => Promise<void>;
  /** Selects the current video input.
   *
   * @example
   * ```ts
   *  try {
   *   selectVideoInput(device)
   *  } catch(e) {
   *   if (e instanceof UserDeniedPermissionError) {
   *
   *   }
   *   if (e instanceof DevicesNotFoundError) {
   *
   *   }
   *  }
   * ```
   */
  selectVideoInput: (device: LocalVideoInputDevice) => Promise<void>;
  /** Mute and unmute the current audio input. */
  muteAllAudioInput: (isMuted: boolean) => Promise<void>;
  /** Mute and unmute the current video input. */
  muteAllVideoInput: (isMuted: boolean) => Promise<void>;
  /** Mute and unmute the current audio input. */
  muteAudioInput: (stream: MediaStream, isMuted: boolean) => Promise<void>;
  /** Mute and unmute the current video input. */
  muteVideoInput: (stream: MediaStream, isMuted: boolean) => Promise<void>;
  /**
   * Returns MediaStream which represents a current audio input.
   *
   * If the current audio input is changed the MediaStream remains the same,
   * only its tracks are replaced.
   *
   * @default options.isMuted = true
   */
  getSelectedAudioInputStream: (
    options?: GetSelectedAudioInputOptions,
  ) => Promise<MediaStream>;
  /**
   * Returns MediaStream which represents a current video input.
   *
   * If the current video input is changed the MediaStream remains the same,
   * only its tracks are replaced.
   *
   * @default options.isMuted = true
   */
  getSelectedVideoInputStream: (
    options?: GetSelectedVideoInputOptions,
  ) => Promise<MediaStream>;
  /**
   * Returns MediaStream of a provided local audio input.
   */
  getAudioInputStream: (options: AudioInputOptions) => Promise<MediaStream>;
  /**
   * Returns MediaStream of a provided local video input.
   */
  getVideoInputStream: (options: VideoInputOptions) => Promise<MediaStream>;
  /**
   * Returns audio and video streams of a local display media if they are available.
   */
  getDisplayInputStream: (
    options?: DisplayInputOptions,
  ) => Promise<MediaStream>;
  /**
   * Releasing an unused media stream.
   */
  releaseMediaStream: (stream: MediaStream) => Promise<void>;
  getMediaStreamState: (
    stream: MediaStream,
  ) => LocalDevicesMediaStreamState | undefined;
  isEnableAudioAGC: QueryAtom<boolean>;
  setAudioAGC: (enabled: boolean) => void;
  audioInputSwitchingMode: QueryAtom<SwitchingMode>;
  setAudioInputSwitchingMode: (mode: SwitchingMode) => void;
  videoInputSwitchingMode: QueryAtom<SwitchingMode>;
  setVideoInputSwitchingMode: (mode: SwitchingMode) => void;
  audioOutputSwitchingMode: QueryAtom<SwitchingMode>;
  setAudioOutputSwitchingMode: (mode: SwitchingMode) => void;
  isAvailableScreenCapture: Atom<boolean>;
  setEffect: (
    stream: MediaStream,
    effect: LocalTrackEffect | undefined,
  ) => Promise<void>;
};

type LocalDeviceManagerPlugin = {
  localDeviceManager: LocalDevicesManager;
};
declare function localDeviceManagerPlugin(): JazzSdkPlugin<LocalDeviceManagerPlugin>;

/**
 * Returns the instance of LocalDeviceManager.
 */
declare function getLocalDevices<
  R extends JazzRoomExtender[],
  C extends JazzClientExtender[],
>(sdk: JazzSdk | JazzRoom<R> | JazzClient<C>): LocalDevicesManager;

type RegisterId = symbol;
type Unsubscribe = () => void;
type RegisterInfo = Readonly<{
  id: RegisterId;
  unregister: Unsubscribe;
}>;
type DisplayEndpointsService = Readonly<{
  registerUsage: (
    participantId: JazzRoomParticipantId,
    request: JazzRoomVideoRequest,
  ) => RegisterInfo;
  /** @deprecated please use setUsageSize */
  setUsageHeight: (
    participantId: JazzRoomParticipantId,
    source: JazzRoomVideoSource,
    id: RegisterId,
    height: number,
  ) => void;
  /** @deprecated please use setUsageSize */
  setUsageQuality: (
    participantId: JazzRoomParticipantId,
    source: JazzRoomVideoSource,
    id: RegisterId,
    quality: JazzRoomVideoQuality,
  ) => void;
  setUsageSize: (
    participantId: JazzRoomParticipantId,
    source: JazzRoomVideoSource,
    id: RegisterId,
    width: number,
    height: number,
  ) => void;
  clearUsage: (participantId: JazzRoomParticipantId) => void;
}>;

declare function getDisplayEndpoints<R extends JazzRoomExtender[]>(
  room: JazzRoom<R>,
): DisplayEndpointsService;

declare const displayEndpointsPlugin: () => JazzSdkPlugin;

type PowerProfilePluginCPUUsages = {
  app: {
    cpu: number;
    memory: number;
  };
  system?: {
    cpu: number;
    memory: number;
  };
};
type PowerProfilePluginCPUEvents = {
  usage: PowerProfilePluginCPUUsages;
  degradation: undefined | PowerProfilePluginCPUUsages;
  normalize: undefined | PowerProfilePluginCPUUsages;
};

type PowerProfilePluginDegradationCameraEvents = {
  degradation: {
    level: number;
  };
  normalize: {
    level: number;
  };
};

type PowerProfilePluginMediaDegradationReason =
  | 'connectionQiality'
  | 'fps'
  | 'packetsLost'
  | 'limitationCameraCPU';
type PowerProfilePluginMediaEvents = {
  degradation: {
    reasons: PowerProfilePluginMediaDegradationReason[];
  };
  normalize: undefined;
};

type PowerProfilePluginEvents = UtilsTypeAddNamespaceToEvents<
  'cpu',
  PowerProfilePluginCPUEvents
> &
  UtilsTypeAddNamespaceToEvents<'media', PowerProfilePluginMediaEvents> &
  UtilsTypeAddNamespaceToEvents<
    'degradeCamera',
    PowerProfilePluginDegradationCameraEvents
  >;
type PowerProfilePluginService = {
  on: SubscribeNode<PowerProfilePluginEvents>['on'];
  once: SubscribeNode<PowerProfilePluginEvents>['once'];
  off: SubscribeNode<PowerProfilePluginEvents>['off'];
};

declare function getPowerProfileService(
  room: JazzRoom,
): PowerProfilePluginService;

type MediaMetricsFlags = ConfigFlags<{
  /**
   * The interval for collecting statistics.
   * Statistics are collected exclusively during the conference.
   *
   * @default 5_000 ms
   */
  interval: number;
  /**
   * Automatic start of statistics collection at the entrance to the conference.
   * If the flag is enabled, statistics are collected once
   * in a while (changed by the interval setting).
   *
   * If the setting is disabled,
   * the start and stop of statistics collection can be controlled using
   * the startCollectMetrics and stopCollectMetrics methods,
   * or to collect statistics by calling the collectClientMetrics method.
   *
   * @default true
   */
  autoStartCollectMetricsEnabled: boolean;
  /**
   * Bigger values are counted as an error.
   *
   * @default 20 ms
   */
  errorThresholdJitter: number;
  /**
   * Bigger values are counted as an error.
   *
   * @default 5 %
   */
  errorThresholdPacketLost: number;
  /**
   * Bigger values are counted as an error.
   *
   * @default 200 ms
   */
  errorThresholdRtt: number;
}>;

type MediaMetricsPluginSettings = MediaMetricsFlags;
type MediaMetricsPluginOptions = Partial<MediaMetricsPluginSettings>;

/**
 * Plugin for getting media statistics
 */
declare function mediaMetricsPlugin(
  options?: MediaMetricsPluginOptions,
): JazzSdkPlugin;

type RtcParticipantSid = string;
type ConnectionQualityName = 'EXCELLENT' | 'GOOD' | 'POOR' | 'LOST';
type ConnectionQualityUpdate = {
  participantSid: RtcParticipantSid;
  quality: ConnectionQualityName;
  score: number;
};
type ConnectionQuality = {
  quality: ConnectionQualityUpdate['quality'];
  score: ConnectionQualityUpdate['score'];
};
type ConnectionStatus = 'active' | 'inactive' | 'interrupted' | 'restoring';
type ConnectionQualityEvents = {
  connectionQualityUpdate: {
    participantId: JazzRoomParticipantId;
    quality: ConnectionQualityUpdate['quality'];
    score: ConnectionQualityUpdate['score'];
  };
  connectionStatusUpdate: {
    participantId: JazzRoomParticipantId;
    status: ConnectionStatus;
  };
};
type ConnectionQualities = Map<JazzRoomParticipantId, ConnectionQuality>;
/**
 * A service for tracking the connection status of users in a conference.
 */
type ConnectionQualityService = {
  on: TransportRoot<ConnectionQualityEvents>['on'];
  once: TransportRoot<ConnectionQualityEvents>['once'];
  off: TransportRoot<ConnectionQualityEvents>['off'];
  connectionQualities: Atom<ConnectionQualities>;
  getConnectionQuality: (
    participantId: JazzRoomParticipantId,
  ) => Atom<ConnectionQuality>;
};

type RTCCommonPeerConnectionStatsReading = {
  peerConnection?: RTCPeerConnectionStats;
  mediaPlayout?: RTCAudioPlayoutStats;
  dataChannels?: Record<RTCDataChannelStats['id'], RTCDataChannelStats>;
  /** after start media channel */
  certificates?: Record<RTCCertificateStats['id'], RTCCertificateStats>;
  localCandidates?: Record<
    RTCIceLocalCandidateStats['id'],
    RTCIceLocalCandidateStats
  >;
  remoteCandidates?: Record<
    RTCIceRemoteCandidateStats['id'],
    RTCIceRemoteCandidateStats
  >;
  codecs?: Record<RTCCodecStats['id'], RTCCodecStats>;
  candidatePairsSucceededId?: RTCIceCandidatePairStats['id'];
  candidatePairs?: Record<
    RTCIceCandidatePairStats['id'],
    RTCIceCandidatePairStats
  >;
  transport?: RTCTransportStats;
};
type RTCCommonStats = {
  /**
   * A string that uniquely identifies the object that
   * is being monitored to produce this set of statistics
   */
  id: string;
  /**
   * A DOMHighResTimeStamp object indicating the time at which the
   * sample was taken for this statistics object.
   */
  timestamp: number;
  /**
   * A string indicating the type of statistics that the object contains.
   */
  type: string;
};
/**
 * Statistics describing the state of the RTCPeerConnection.
 */
type RTCPeerConnectionStats = RTCCommonStats & {
  type: 'peer-connection';
  /**
   * A positive integer value indicating the number of unique RTCDataChannel objects
   * that have entered the open state during their lifetime.
   */
  dataChannelsOpened: number;
  /**
   * A positive integer value indicating the number of unique RTCDataChannel objects
   * that have left the open state during their lifetime
   * (channels that transition to closing or closed without ever being open are not counted in this number).
   * A channel will leave the open state if either end of the connection or the underlying transport is closed.
   */
  dataChannelsClosed: number;
};
/**
 * Statistics related to audio playout. It is accessed by the RTCAudioPlayoutStats.
 *
 * not supported in Safari and Firefox
 */
type RTCAudioPlayoutStats = RTCCommonStats & {
  type: 'media-playout';
  /**
   * For audio playout, this has the value "audio".
   * This reflects the kind attribute MediaStreamTrack(s) being played out.
   */
  kind: MediaStreamTrack['kind'];
  /**
   * If the playout path is unable to produce audio samples on time for device playout,
   * samples are synthesized to be playout out instead.
   * synthesizedSamplesDuration is measured in seconds and is incremented each time
   * an audio sample is synthesized by this playout path. This metric can be used together
   * with total Samples Duration to calculate the percentage of played out media being synthesized.
   *
   * Synthesization typically only happens if the pipeline is underperforming.
   * Samples synthesized by the RTCInboundRtpStreamStats are not counted for here,
   * but in RTCInboundRtpStreamStats.concealedSamples.
   */
  synthesizedSamplesDuration: number;
  /**
   * The number of synthesized samples events.
   * This counter increases every time a sample is synthesized after a non-synthesized sample.
   * That is, multiple consecutive synthesized samples will increase synthesizedSamplesDuration
   * multiple times but is a single synthesization samples event.
   */
  synthesizedSamplesEvents: number;
  /**
   * The total duration, in seconds, of all audio samples that have been playout.
   * Includes both synthesized and non-synthesized samples.
   */
  totalSamplesDuration: number;
  /**
   * When audio samples are pulled by the playout device,
   * this counter is incremented with the estimated delay of the playout path for that audio sample.
   * The playout delay includes the delay from being emitted to the actual time of playout on the device.
   * This metric can be used together with totalSamplesCount
   * to calculate the average playout delay per sample.
   */
  totalPlayoutDelay: number;
  /**
   * When audio samples are pulled by the playout device,
   * this counter is incremented with the number of samples emitted for playout.
   */
  totalSamplesCount: number;
};
/**
 * Statistics about a certificate being used by an RTCIceTransport.
 *
 * not Supported in Firefox
 */
type RTCCertificateStats = RTCCommonStats & {
  type: 'certificate';
  /**
   * A string containing the base-64 representation of the DER-encoded certificate.
   */
  base64Certificate: string;
  /**
   * A string containing the certificate fingerprint,
   * which is calculated using the hash function specified in fingerprintAlgorithm.
   */
  fingerprint: string;
  /**
   * A string containing the hash function used to compute the certificate fingerprint, such as "sha-256".
   */
  fingerprintAlgorithm: string;
  /**
   * The issuerCertificateId refers to the stats object that contains the next certificate in the certificate chain.
   * If the current certificate is at the end of the chain (i.e. a self-signed certificate), this will not be set
   */
  issuerCertificateId?: string;
};
/**
 * Statistics about a local ICE candidate associated with the connection's RTCIceTransports.
 */
type RTCIceLocalCandidateStats = RTCIceCandidateStats & {
  type: 'local-candidate';
  /**
   * not-documentation
   */
  networkType: string;
};
/**
 * Statistics about a remote ICE candidate associated with the connection's RTCIceTransports.
 */
type RTCIceRemoteCandidateStats = RTCIceCandidateStats & {
  type: 'remote-candidate';
  /**
   * The ICE rel-addr defined in [RFC5245] section 15.1.
   * Only set for serverreflexive, peerreflexive and relay candidates.
   */
  relatedAddress?: RTCIceCandidate['relatedAddress'];
  /**
   * The ICE rel-addr defined in [RFC5245] section 15.1.
   * Only set for serverreflexive, peerreflexive and relay candidates.
   */
  relatedPort?: RTCIceCandidate['relatedPort'];
};
/**
 * Statistics about a remote ICE candidate associated with the connection's RTCIceTransports.
 */
type RTCIceCandidateStats = RTCCommonStats & {
  /**
   * It is a unique identifier that is associated to the object that
   * was inspected to produce the RTCTransportStats associated with this candidate.
   */
  transportId: RTCTransportStats['id'];
  /**
   * A string containing the address of the candidate.
   * This value may be an IPv4 address, an IPv6 address,
   * or a fully-qualified domain name. This property was
   * previously named ip and only accepted IP addresses.
   *
   * not supported in Safari
   */
  address?: RTCIceCandidate['address'];
  /**
   * A string containing the address of the candidate.
   * This value may be an IPv4 address, an IPv6 address,
   * or a fully-qualified domain name. This property was
   * previously named ip and only accepted IP addresses.
   *
   * not supported in Safari
   */
  ip?: RTCIceCandidate['address'];
  /**
   * A string matching one of the values in RTCIceCandidate.type,
   * indicating what kind of candidate the object provides statistics for.
   */
  candidateType: RTCIceCandidate['type'];
  /**
   * A Boolean value indicating whether or not the candidate has been released or deleted;
   * the default value is false. For local candidates,
   * its value is true if the candidate has been deleted or released.
   * For host candidates, true means that any network resources (usually a network socket)
   * associated with the candidate have already been released.
   * For TURN candidates, the TURN allocation is no longer active for deleted candidates.
   * This property is not present for remote candidates
   */
  deleted?: boolean;
  /**
   * The network port number used by the candidate.
   */
  port?: RTCIceCandidate['port'];
  /**
   * The candidate's priority, corresponding to RTCIceCandidate.priority.
   */
  priority?: RTCIceCandidate['priority'];
  /**
   * A string specifying the protocol (tcp or udp) used to transmit data on the port.
   */
  protocol?: RTCIceCandidate['protocol'];
  /**
   * A string identifying the protocol used by the endpoint for communicating with the TURN server;
   * valid values are tcp, udp, and tls. Only present for local candidates.
   */
  relayProtocol?: RTCIceCandidate['protocol'] | 'tls';
  /**
   * For local candidates, the url property is the URL of the ICE server
   * from which the candidate was received. This URL matches the one included
   * in the RTCPeerConnectionIceEvent object representing the icecandidate event
   * that delivered the candidate to the local peer.
   */
  url?: string;
  /**
   * (experimental) The ICE foundation as defined in [RFC5245] section 15.1
   *
   * not supported in Firefox and Safari
   */
  foundation?: RTCIceCandidate['foundation'];
  /**
   * The ICE username fragment as defined in [RFC5245] section 7.1.2.3.
   *
   * Not supported in Safari and Firefox
   */
  usernameFragment?: RTCIceCandidate['usernameFragment'];
  /**
   * The ICE candidate TCP type, as defined іn RTCIceTcpCandidateType and used in RTCIceCandidate.
   */
  tcpType: RTCIceCandidate['tcpType'];
  /**
   * not-documentation API
   */
  isRemote?: boolean;
};
type RTCIceCandidatePairStats = RTCCommonStats & {
  type: 'candidate-pair';
  /**
   * A number representing the available inbound capacity of the network.
   * This reports the total number of bits per second available for all of the candidate pair's incoming RTP streams.
   * It does not take into account the size of the Internet Protocol (IP) overhead,
   * nor any other transport layers such as TCP or UDP.
   */
  availableIncomingBitrate?: number;
  /**
   * A number representing the approximate available outbound capacity of the network.
   * This reports the total number of bits per second available for all of the candidate pair's outgoing RTP streams.
   * It does not take into account the size of the IP overhead, nor any other transport layers such as TCP or UDP.
   *
   * not supported Firefox and Safari
   */
  availableOutgoingBitrate?: number;
  /**
   * An integer representing the total number of bytes discarded due to socket errors on this candidate pair.
   *
   * Experimental
   *
   * not supported Firefox and Safari
   */
  bytesDiscardedOnSend?: number;
  /**
   * An integer representing the total number of payload bytes received on this candidate pair.
   */
  bytesReceived?: number;
  /**
   * An integer representing the total number of payload bytes sent on this candidate pair
   * (the total number of bytes sent excluding any headers, padding, or other protocol overhead).
   */
  bytesSent?: number;
  /**
   * An integer representing the total number of STUN consent requests sent on this candidate pair.
   *
   * Experimental
   *
   * not supported Firefox and Safari
   */
  consentRequestsSent?: number;
  /**
   * A number representing the total time, in seconds,
   * that elapsed between the most recently-sent STUN request and the response being received.
   * This may be based upon requests that were involved in confirming permission to open the connection.
   *
   * not supported Firefox and Safari
   */
  currentRoundTripTime?: number;
  /**
   * A DOMHighResTimeStamp value indicating the time at which
   * the last packet was received by the local peer from the remote peer for this candidate pair.
   * Timestamps are not recorded for STUN packets.
   *
   * not supported Safari
   */
  lastPacketReceivedTimestamp?: number;
  /**
   * A DOMHighResTimeStamp value indicating the time at which
   * the last packet was sent from the local peer to the remote peer for this candidate pair.
   * Timestamps are not recorded for STUN packets.
   *
   * not supported Safari
   */
  lastPacketSentTimestamp?: number;
  /**
   * A string representing the unique ID corresponding to the RTCIceCandidate
   * from the data included in the RTCIceCandidateStats object providing statistics
   * for the candidate pair's local candidate.
   */
  localCandidateId?: RTCIceCandidateStats['id'];
  /**
   * A string containing a unique ID corresponding to the remote candidate from
   * which data was taken to construct the RTCIceCandidateStats object describing
   * the remote end of the connection.
   */
  remoteCandidateId?: RTCIceCandidateStats['id'];
  /**
   * A Boolean value which, if true, indicates that the candidate pair described
   * by this object is one which has been proposed for use, and will be (or was)
   * used if its priority is the highest among the nominated candidate pairs.
   * See RFC 5245, section 7.1.3.2.4 for details.
   */
  nominated?: boolean;
  /**
   * An integer representing the total number of packets discarded due
   * to socket errors on this candidate pair.
   *
   * Experimental
   *
   * not supported Firefox and Safari
   */
  packetsDiscardedOnSend?: number;
  /**
   * An integer representing the total number of packets received on this candidate pair.
   *
   * Experimental
   *
   * not supported Firefox and Safari
   */
  packetsReceived?: number;
  /**
   * An integer representing the total number of packets sent on this candidate pair.
   *
   * Experimental
   *
   * not supported Firefox and Safari
   */
  packetsSent?: number;
  /**
   * An integer representing the total number of connectivity
   * check requests that have been received, including retransmissions.
   * This value includes both connectivity checks and STUN consent checks.
   *
   * not supported Firefox
   */
  requestsReceived?: number;
  /**
   * An integer representing the total number of connectivity
   * check requests that have been sent, not including retransmissions.
   *
   * not supported Firefox
   */
  requestsSent?: number;
  /**
   * An integer representing the total number of connectivity check responses that have been received.
   *
   * not supported Firefox
   */
  responsesReceived?: number;
  /**
   * An integer representing the total number of connectivity check responses that have been sent.
   * This includes both connectivity check requests and STUN consent requests.
   */
  responsesSent?: number;
  /**
   * A string which indicates the state of the connection between the two candidates.
   *
   * https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePairStats/state
   */
  state?:
    | 'failed'
    /**
     * No check has been performed yet for this candidate pair,
     * and performing the check is blocked until another check is successful.
     * Once that check has succeeded, this pair will unfreeze and move into the waiting state.
     */
    | 'frozen'
    /**
     * A check has been initiated for this pair,
     * but the check's transaction is still in progress.
     */
    | 'in-progress'
    /**
     * A check for this pair has been completed successfully.
     */
    | 'succeeded'
    /**
     * This pair has not yet been checked,
     * but the check can be performed as soon as this pair is the highest priority pair
     * remaining in the waiting state.
     */
    | 'waiting';
  /**
   * A number indicating the total time, in seconds, that has elapsed
   * between sending STUN requests and receiving responses to them,
   * for all such requests made to date on this candidate pair.
   * This includes both connectivity check and consent check requests.
   * You can compute the average round trip time (RTT) by dividing this value by responsesReceived.
   *
   * not supported Firefox
   */
  totalRoundTripTime?: number;
  /**
   * A string that uniquely identifies the RTCIceTransport that was inspected
   * to obtain the transport-related statistics (as found in RTCTransportStats)
   * used in generating this object.
   */
  transportId?: RTCTransportStats['id'];
  /**
   * An integer value indicating the candidate pair's priority.
   * @deprecated
   *
   * not supported Safari
   */
  priority?: number;
  /**
   * A Boolean value indicating whether or not data
   * can be sent over the connection described by the candidate pair.
   *
   * @deprecated
   */
  readable?: boolean;
  /**
   * A Boolean value indicating whether or not data can be received
   * on the connection described by the candidate pair.
   *
   * @deprecated
   */
  writable?: boolean;
};
/**
 * Statistics about a transport used by the connection.
 *
 * Not supported in Firefox
 */
type RTCTransportStats = RTCCommonStats & {
  type: 'transport';
  /**
   * The total number of payload bytes received on this transport
   * (bytes received, not including headers, padding or ICE connectivity checks).
   *
   * Not supported in Firefox
   */
  bytesReceived?: number;
  /**
   * The total number of payload bytes sent on this transport
   * (bytes sent, not including headers, padding or ICE connectivity checks).
   *
   * Not supported in Firefox
   */
  bytesSent?: number;
  /**
   * A string indicating the name of the cipher suite used for the DTLS transport,
   * as defined in the "Description" column of the TLS Cipher Suites section in the IANA cipher suite registry.
   * For example "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256".
   *
   * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
   *
   * Not supported in Firefox
   */
  dtlsCipher?: string;
  /**
   * The DTLS role of the associated RTCPeerConnection.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  dtlsRole?:
    | 'client'
    | 'server'
    /**
     * before the DTLS negotiation starts
     */
    | 'unknown';
  /**
   * The state read-only property of the RTCDtlsTransport interface provides
   * information which describes a Datagram Transport Layer Security (DTLS) transport state.
   *
   * Not supported in Firefox
   */
  dtlsState?:
    | 'new'
    /**
     * DTLS is in the process of negotiating a secure connection and verifying the remote fingerprint.
     */
    | 'connecting'
    /**
     * DTLS has completed negotiation of a secure connection and verified the remote fingerprint.
     */
    | 'connected'
    /**
     * The transport has been closed intentionally as the result of receipt
     * of a close_notify alert, or calling RTCPeerConnection.close().
     */
    | 'closed'
    /**
     * The transport has failed as the result of an error
     * (such as receipt of an error alert or failure to validate the remote fingerprint).
     */
    | 'failed';
  /**
   * A string indicating the local username fragment used in message validation procedures for this transport.
   * This is the same value as the local RTCIceCandidate.usernameFragment,
   * and will change if the connection is renegotiated.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  iceLocalUsernameFragment?: RTCIceCandidate['usernameFragment'];
  /**
   * The role read-only property of the RTCIceTransport interface indicates
   * which ICE role the transport is fulfilling: that of the controlling agent,
   * or the agent that is being controlled.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  iceRole?:
    | 'controlled'
    /**
     * The RTCIceTransport object is serving as the controlling agent.
     */
    | 'controlling'
    /**
     * The role has not yet been determined.
     */
    | 'unknown';
  /**
   * The state read-only property of the RTCIceTransport interface returns the current state of the ICE transport,
   * so you can determine the state of ICE gathering in which the ICE agent currently is operating.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  iceState?:
    | 'new'
    /**
     * At least one remote candidate has been received,
     * and the RTCIceTransport has begun examining pairings of remote and local candidates
     * in order to attempt to identify viable pairs that could be used to establish a connection.
     * Keep in mind that gathering of local candidates may still be underway, and, similarly,
     * the remote device also may still be gathering candidates of its own.
     */
    | 'checking'
    /**
     * A viable candidate pair has been found and selected,
     * and the RTCIceTransport has connected the two peers together using that pair.
     * However, there are still candidates pairings to consider, and there may still
     * be gathering underway on one or both of the two devices.
     *
     * The transport may revert from the "connected" state to the "checking" state
     * if either peer decides to cancel consent to use the selected candidate pair,
     * and may revert to "disconnected" if there are no candidates left to check
     * but one or both clients are still gathering candidates.
     */
    | 'connected'
    /**
     * The transport has finished gathering local candidates and has received a notification
     * from the remote peer that no more candidates will be sent.
     * In addition, all candidate pairs have been considered
     * and a pair has been selected for use. If consent checks fail
     * on all successful candidate pairs, the transport state will change to "failed".
     */
    | 'completed'
    /**
     * The ICE agent has determined that connectivity has been lost for this RTCIceTransport.
     * This is not a failure state (that's "failed").
     * A value of "disconnected" means that a transient issue has occurred
     * that has broken the connection, but that should resolve itself automatically
     * without your code having to take any action. See The disconnected state for additional details.
     */
    | 'disconnected'
    /**
     * The RTCIceTransport has finished the gathering process,
     * has received the "no more candidates" notification from the remote peer,
     * and has finished checking pairs of candidates,
     * without successfully finding a pair that is both valid and for which consent can be obtained.
     * This is a terminal state, indicating that the connection cannot be achieved or maintained.
     */
    | 'failed'
    /**
     * The transport has shut down and is no longer responding to STUN requests.
     */
    | 'closed';
  /**
   * A string containing the unique identifier for the object
   * that was inspected to produce the RTCIceCandidatePairStats associated with this transport.
   *
   * Not supported in Firefox
   */
  selectedCandidatePairId?: RTCIceCandidatePairStats['id'];
  /**
   * A string containing the id of the local certificate used by this transport.
   * Only present for DTLS transports, and after DTLS has been negotiated.
   *
   * Not supported in Firefox
   */
  localCertificateId?: RTCCertificateStats['id'];
  /**
   * The total number of packets sent over this transport.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  packetsSent?: number;
  /**
   * The total number of packets received on this transport.
   *
   * Experimental
   *
   * Not supported in Firefox and Safari
   */
  packetsReceived?: number;
  /**
   * A string containing the id or the remote certificate used by this transport.
   * Only present for DTLS transports, and after DTLS has been negotiated.
   *
   * Not supported in Firefox
   */
  remoteCertificateId?: RTCCertificateStats['id'];
  /**
   * The number of times that the selected candidate pair of this transport has changed.
   * The value is initially zero and increases whenever a candidate pair selected or lost.
   *
   * Not supported in Firefox and Safari
   */
  selectedCandidatePairChanges?: number;
  /**
   * A string indicating the descriptive name of the protection profile used
   * for the Secure Real-time Transport Protocol (SRTP) transport,
   * as defined in the "Profile" column of the IANA DTLS-SRTP protection profile registry and RFC5764.
   *
   * https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
   * https://www.rfc-editor.org/rfc/rfc5764.html#section-4.1.2
   *
   * For example "AES_CM_128_HMAC_SHA1_80" specifies the following profile,
   * where maximum_lifetime is the maximum number of packets that can be protected by a single set of keys.
   *
   * Not supported in Firefox
   */
  srtpCipher?: string;
  /**
   * A string containing the negotiated TLS version.
   * This is present for DTLS transports,
   * and only exists after DTLS has been negotiated.
   *
   * The value comes from the DTLS handshake ServerHello.version,
   * and is represented as four upper case hexadecimal digits,
   * where the digits represent the two bytes of the version.
   * Note however that the bytes might not map directly to version numbers.
   * For example, DTLS represents version 1.2 as 'FEFD' which numerically is {254, 253}.
   *
   * Not supported in Firefox
   */
  tlsVersion?: string;
};
/**
 * Statistics related to one RTCDataChannel on the connection.
 */
type RTCDataChannelStats = RTCCommonStats & {
  type: 'data-channel';
  /**
   * A positive integer value indicating the total number
   * of payload bytes sent on the associated RTCDataChannel.
   */
  bytesSent?: number;
  /**
   * A positive integer value indicating the total number
   * of payload bytes received on the associated RTCDataChannel.
   */
  bytesReceived?: number;
  /**
   * A positive integer value containing the id of the associated RTCDataChannel.
   */
  dataChannelIdentifier?: RTCDataChannel['id'];
  /**
   * A string containing the label of the associated RTCDataChannel.
   */
  label?: RTCDataChannel['label'];
  /**
   * A positive integer value indicating the total number
   * of message events fired for received messages on the associated RTCDataChannel.
   */
  messagesReceived?: number;
  /**
   * A positive integer value indicating the total number
   * of message events fired for sent messages on the channel.
   */
  messagesSent?: number;
  /**
   * A string containing the protocol of the associated RTCDataChannel.
   */
  protocol?: RTCDataChannel['protocol'];
  /**
   * The readyState of the associated RTCDataChannel.
   */
  state: RTCDataChannel['readyState'];
};
/**
 * Statistics about a specific codec being used by streams being sent or received by this connection.
 */
type RTCCodecStats = RTCCommonStats & {
  type: 'codec';
  /**
   * A positive number indicating the number of channels supported by the codec.
   */
  channels?: number;
  /**
   * A positive number containing the media sampling rate.
   */
  clockRate?: number;
  /**
   * A string containing the media MIME type/subtype, such as video/VP8.
   */
  mimeType: string;
  /**
   * A positive integer value in the range of 0 to 127
   * indicating the payload type used in RTP encoding or decoding.
   */
  payloadType: number;
  /**
   * A string containing the format-specific parameters
   * of the "a=fmtp" line in the codec's SDP (if present).
   */
  sdpFmtpLine: string;
  /**
   * It is a unique identifier that is associated to the object that
   * was inspected to produce the RTCTransportStats associated with this candidate.
   *
   * not supported in Safari
   */
  transportId: RTCTransportStats['id'];
};
type RTCMediaSourceStats = RTCCommonStats & {
  /**
   * A string indicating whether this object represents stats for a video source or a media source.
   * For an RTCAudioSourceStats this will always be audio.
   * For an RTCVideoSourceStats this will always be video.
   */
  kind: MediaStreamTrack['kind'];
  /**
   * A string that contains the id value of the MediaStreamTrack associated with the audio or video source.
   */
  trackIdentifier: MediaStreamTrack['id'];
  /**
   * The id of the RTCSenderAudioTrackAttachmentStats or RTCSenderVideoTrackAttachmentStats
   * object containing the current track attachment to the RTCRtpSender responsible for this stream.
   *
   * @deprecated
   */
  trackId?: string;
};
type RTCRtpStreamStats = {
  /**
   * A string that uniquely identifies the object that
   * was inspected to produce the RTCCodecStats object
   * associated with this RTP stream.
   */
  codecId?: RTCCodecStats['id'];
  /**
   * A string that uniquely identifies the object which was inspected
   * to produce the RTCTransportStats object associated with this RTP stream.
   *
   * not supported in Firefox
   */
  transportId?: RTCTransportStats['id'];
  /**
   * A string indicating whether the MediaStreamTrack
   * associated with the stream is an audio or a video track.
   */
  kind: MediaStreamTrack['kind'];
  /**
   * A positive integer that identifies the SSRC of the RTP packets in this stream.
   */
  ssrc: number;
};
type RTCReceivedRtpStreamStats = {
  /**
   * A number indicating the packet jitter for this synchronization source,
   * measured in seconds.
   *
   * https://developer.mozilla.org/en-US/docs/Glossary/Jitter
   *
   * not supported in Safari
   */
  jitter?: number;
  /**
   * An integer indicating the total number of RTP packets lost for this SSRC,
   * as measured at the remote endpoint.
   * This value can be negative if duplicate packets were received.
   *
   * not supported in Safari
   */
  packetsLost?: number;
  /**
   * A positive integer indicating the total number
   * of RTP packets received for this SSRC,
   * including retransmissions.
   *
   * Experimental
   *
   * not supported in Chrome, Edge, Opera and Safari
   */
  packetsReceived?: number;
};
type RTCSentRtpStreamStats = RTCMediaSourceStats &
  RTCRtpStreamStats & {
    /**
     * Total number of RTP packets sent for this SSRC.
     * This includes retransmissions.
     * Calculated as defined in [RFC3550] section 6.4.1.
     *
     * not Supported in Safari
     */
    packetsSent?: number;
    /**
     * Total number of bytes sent for this SSRC.
     * This includes retransmissions.
     * Calculated as defined in [RFC3550] section 6.4.1.
     *
     * not Supported in Safari
     */
    bytesSent?: number;
  };

type RTCPublisherPeerConnectionStatsReading =
  RTCCommonPeerConnectionStatsReading & {
    /** for media tracks  */
    audioTracks?: Record<RTCAudioSourceStats['id'], RTCAudioSourceStats>;
    videoTracks?: Record<RTCVideoSourceStats['id'], RTCVideoSourceStats>;
    /**
     * mediaSourceId => RTCAudioSourceStats['id'] not Firefox
     * remoteId => RTCRemoteInboundRtpAudioStreamStats['id'] not Safari 15.3
     */
    outboundAudioTracks?: Record<
      RTCOutboundRtpAudioStreamStats['ssrc'],
      RTCOutboundRtpAudioStreamStats
    >;
    outboundVideoTracks?: Record<
      RTCOutboundRtpVideoStreamStats['ssrc'],
      RTCOutboundRtpVideoStreamStats
    >;
    /**
     * Safari 15.3 not have remoteId for mapping data
     * if there is no remote Id, another flow parsing is used.
     * or 'remote-inbound-rtp' not allowed
     */
    outboundAudioTrackHasRemoteId: boolean;
    outboundVideoTrackHasRemoteId: boolean;
    outboundAudioTracksHasRemoteId?: Record<
      RTCOutboundRtpAudioStreamStats['ssrc'],
      boolean
    >;
    outboundVideoTracksHasRemoteId?: Record<
      RTCOutboundRtpVideoStreamStats['ssrc'],
      boolean
    >;
    remoteInboundsAudioTracks?: Record<
      RTCRemoteInboundRtpAudioStreamStats['id'],
      RTCRemoteInboundRtpAudioStreamStats
    >;
    remoteInboundsVideoTracks?: Record<
      RTCRemoteInboundRtpVideoStreamStats['id'],
      RTCRemoteInboundRtpVideoStreamStats
    >;
  };
type RTCPublisherPeerConnectionStats =
  | RTCPeerConnectionStats
  | RTCAudioPlayoutStats
  | RTCCertificateStats
  | RTCIceLocalCandidateStats
  | RTCIceRemoteCandidateStats
  | RTCDataChannelStats
  | RTCCodecStats
  | RTCIceCandidatePairStats
  | RTCTransportStats
  | RTCVideoSourceStats
  | RTCAudioSourceStats
  | RTCRemoteInboundRtpVideoStreamStats
  | RTCRemoteInboundRtpAudioStreamStats
  | RTCOutboundRtpVideoStreamStats
  | RTCOutboundRtpAudioStreamStats;
/**
 * The RTCVideoSourceStats dictionary represents a video track that is attached to one or more senders.
 * It is an RTCMediaSourceStats whose kind is "video".
 */
type RTCVideoSourceStats = RTCMediaSourceStats & {
  type: 'media-source';
  kind: 'video';
  /**
   * A positive number that indicates the total number of frames originating from this video source.
   *
   * not supported in Safari
   */
  frames?: number;
  /**
   * A positive number that represents the number of frames originating from this video source in the last second.
   * This property is not defined on this stats object for the first second of its existence.
   *
   * not supported in Safari
   */
  framesPerSecond?: number;
  /**
   * A number that represents the height, in pixels, of the last frame originating from this source.
   * This property is not defined on this stats object until after the first frame has been produced.
   *
   * not supported in Safari
   */
  height?: number;
  /**
   * A number that represents the width, in pixels, of the most recent frame originating from this source.
   * This property is not defined on this stats object until after the first frame has been produced.
   *
   * not supported in Safari
   */
  width?: number;
};
/**
 * Statistics about the media produced by the MediaStreamTrack attached to an RTP sender.
 * The dictionary this key maps to depends on the track's kind.
 */
type RTCAudioSourceStats = RTCMediaSourceStats & {
  type: 'media-source';
  kind: 'audio';
  /**
   * A number that represents the audio level of the media source.
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  audioLevel?: number;
  /**
   * A number that represents the total audio energy
   * of the media source over the lifetime of the stats object.
   *
   * read more
   * https://www.w3.org/TR/webrtc-stats/#webidl-637796216
   * https://developer.mozilla.org/en-US/docs/Web/API/RTCAudioSourceStats
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  totalAudioEnergy?: number;
  /**
   * A number that represents the total duration of all samples produced
   * by the media source over the lifetime of the stats object.
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  totalSamplesDuration?: number;
  /**
   * Only exists when the MediaStreamTrack is sourced from a microphone where echo cancellation is applied.
   * Calculated in decibels, as defined in [ECHO] (2012) section 3.14.
   *
   * If multiple audio channels are used,
   * the channel of the least audio energy is considered for any sample.
   *
   * not supported in Firefox and Safari
   */
  echoReturnLoss?: number;
  /**
   * Only exists when the MediaStreamTrack is sourced from a microphone where echo cancellation is applied.
   * Calculated in decibels, as defined in [ECHO] (2012) section 3.15.
   *
   * If multiple audio channels are used,
   * the channel of the least audio energy is considered for any sample.
   *
   * not supported in Firefox and Safari
   */
  echoReturnLossEnhancement?: number;
};
/**
 * Statistics describing the state of the inbound data stream from the perspective of the remote peer.
 */
type RTCRemoteInboundRtpVideoStreamStats = RTCRemoteInboundRtpStreamStats & {
  kind: 'video';
};
/**
 * Statistics describing the state of the inbound data stream from the perspective of the remote peer.
 */
type RTCRemoteInboundRtpAudioStreamStats = RTCRemoteInboundRtpStreamStats & {
  kind: 'audio';
};
type RTCRemoteInboundRtpStreamStats = RTCCommonStats &
  RTCReceivedRtpStreamStats &
  RTCRtpStreamStats & {
    type: 'remote-inbound-rtp';
    /**
     * A number indicating the fraction of packets lost
     * for this SSRC since the last sender or receiver report.
     *
     * not supported in Safari
     */
    fractionLost?: number;
    /**
     * A string that is used to find the local RTCOutboundRtpStreamStats object
     * that shares the same synchronization source (SSRC).
     */
    localId?: RTCOutboundRtpStreamStats['id'];
    /**
     * A number that indicates the estimated round trip time (RTT) for this SSRC, in seconds.
     * This property will not exist until valid RTT data has been received.
     */
    roundTripTime?: number;
    /**
     * A positive integer indicating the total number
     * of valid round trip time measurements received for this synchronization source (SSRC).
     *
     * not supported in Safari
     */
    roundTripTimeMeasurements?: number;
    /**
     * A number indicating the cumulative sum of all round trip time measurements since the beginning of the session, in seconds.
     * The average round trip time can be computed by dividing totalRoundTripTime by roundTripTimeMeasurements.
     *
     * not supported in Safari
     */
    totalRoundTripTime?: number;
  };
/**
 * Statistics describing the state of one of the outbound data streams on this connection.
 */
type RTCOutboundRtpVideoStreamStats = RTCOutboundRtpStreamStats & {
  kind: 'video';
  /**
   * An integer value which indicates the total number of Full Intra Request (FIR)
   * packets which this RTCRtpSender has sent to the remote RTCRtpReceiver.
   * This is an indicator of how often the stream has lagged,
   * requiring frames to be skipped in order to catch up.
   * Valid only for video streams.
   */
  firCount?: number;
  /**
   * The number of frames that have been successfully encoded
   * so far for sending on this RTP stream.
   * Only valid for video streams.
   */
  framesEncoded?: number;
  /**
   * An integer specifying the number of times the remote receiver has notified
   * this RTCRtpSender that some amount of encoded video data for one or more frames has been lost,
   * using Picture Loss Indication (PLI) packets.
   * Only available for video streams.
   */
  pliCount?: number;
  /**
   * A 64-bit value containing the sum of the QP values
   * for every frame encoded by this RTCRtpSender.
   * Valid only for video streams.
   *
   * not supported in Safari
   */
  qpSum?: number;
  /**
   * A record of the total time, in seconds, that this stream has spent in each quality limitation state.
   * The record includes a mapping for all RTCQualityLimitationReason types, including "none".
   *
   * The sum of all entries minus qualityLimitationDurations["none"]
   * gives the total time that the stream has been limited.
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  qualityLimitationDurations?: Record<
    Exclude<
      RTCOutboundRtpVideoStreamStats['qualityLimitationReason'],
      undefined
    >,
    number
  >;
  /**
   * The current reason for limiting the resolution and/or framerate, or "none" if not limited.
   *
   * One of the string none, cpu, bandwidth, or other,
   * explaining why the resolution and/or frame rate is being limited for this RTP stream.
   * Valid only for video streams.
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  qualityLimitationReason?: 'none' | 'cpu' | 'bandwidth' | 'other';
  /**
   * The number of times that the resolution has changed because we are quality limited
   * (qualityLimitationReason has a value other than "none").
   * The counter is initially zero and increases when the resolution goes up or down.
   * For example, if a 720p track is sent as 480p for some time and then recovers to 720p,
   * qualityLimitationResolutionChanges will have the value 2.
   */
  qualityLimitationResolutionChanges?: number;
  /**
   * An integer indicating the number of times this sender received a Slice Loss Indication (SLI)
   * frame from the remote peer, indicating
   * that one or more consecutive video macroblocks have been lost or corrupted.
   * Available only for video streams.
   */
  sliCount?: number;
  /**
   * A cumulative sum of the target frame sizes
   * (the targeted maximum size of the frame in bytes when the codec is asked to compress it)
   * for all of the frames encoded so far.
   * This will likely differ from the total of the actual frame sizes.
   *
   * not supported in Safari
   */
  totalEncodedBytesTarget?: number;
  /**
   * A floating-point value indicating the total number
   * of seconds that have been spent encoding
   * the frames encoded so far by this RTCRtpSender.
   *
   * not supported in Safari
   */
  totalEncodeTime?: number;
  /**
   * Only exists if a rid has been set for this RTP stream.
   * If rid is set this value will be present regardless
   * if the RID RTP header extension has been negotiated.
   */
  rid?: string;
  /**
   * Represents the width of the last encoded frame.
   * The resolution of the encoded frame may be lower than the media source
   * (see RTCVideoSourceStats.width).
   * Before the first frame is encoded this member MUST NOT exist.
   *
   * not supported in Safari
   */
  frameWidth?: RTCVideoSourceStats['width'];
  /**
   * Represents the height of the last encoded frame.
   * The resolution of the encoded frame may be lower than the media source
   * (see RTCVideoSourceStats.height).
   * Before the first frame is encoded this member MUST NOT exist.
   *
   * not supported in Safari
   */
  frameHeight?: RTCVideoSourceStats['height'];
  /**
   * The number of encoded frames during the last second.
   * This may be lower than the media source frame rate
   * (see RTCVideoSourceStats.framesPerSecond).
   *
   * not supported in Safari
   */
  framesPerSecond?: RTCVideoSourceStats['framesPerSecond'];
  /**
   * Represents the total number of frames sent on this RTP stream.
   *
   * not supported in Safari
   */
  framesSent?: number;
  /**
   * Represents the total number of huge frames sent by this RTP stream.
   * Huge frames, by definition, are frames that have an encoded size
   * at least 2.5 times the average size of the frames.
   * The average size of the frames is defined as the target bitrate per second divided
   * by the target FPS at the time the frame was encoded.
   * These are usually complex to encode frames with a lot of changes in the picture.
   * This can be used to estimate, e.g slide changes in the streamed presentation.
   */
  hugeFramesSent?: number;
  /**
   *  It represents the total number of key frames,
   * such as key frames in VP8 [RFC6386] or IDR-frames in H.264 [RFC6184],
   * successfully encoded for this RTP media stream. This is a subset of framesEncoded.
   * framesEncoded - keyFramesEncoded gives you the number of delta frames encoded.
   *
   * not supported in Firefox and Safari
   */
  keyFramesEncoded?: number;
  /**
   * MUST NOT exist unless exposing hardware is allowed.
   *
   * Identifies the encoder implementation used.
   * This is useful for diagnosing interoperability issues.
   */
  encoderImplementation?: string;
  /**
   * MUST NOT exist unless exposing hardware is allowed.
   *
   * Whether the encoder currently used is considered power efficient by the user agent.
   * This SHOULD reflect if the configuration results in hardware acceleration,
   * but the user agent MAY take other information into account when deciding
   * if the configuration is considered power efficient.
   */
  powerEfficientEncoder?: boolean;
  /**
   * Only exists when a scalability mode is currently configured for this RTP stream.
   *
   * https://w3c.github.io/webrtc-svc/#scalabilitymodes*
   *
   * Experimental
   *
   * not supported in Firefox and Safari
   */
  scalabilityMode?: string;
};
/**
 * Statistics describing the state of one of the outbound data streams on this connection.
 */
type RTCOutboundRtpAudioStreamStats = RTCOutboundRtpStreamStats & {
  kind: 'audio';
};
type RTCOutboundRtpStreamStats = RTCCommonStats &
  RTCSentRtpStreamStats & {
    type: 'outbound-rtp';
    /**
     * Indicates whether this RTP stream is configured to be sent or disabled.
     * Note that an active stream can still not be sending,
     * e.g. when being limited by network conditions.
     *
     * not supported in Firefox and Safari
     */
    active?: boolean;
    mediaType?: string;
    /**
     * If the RTCRtpTransceiver owning this stream has a mid value that is not null,
     * this is that value, otherwise this member MUST NOT be present.
     *
     * Experimental
     *
     * not supported in Firefox and Safari
     */
    mid?: RTCRtpTransceiver['mid'];
    /**
     * The identifier of the stats object representing the track currently
     * attached to the sender of this stream, an RTCMediaSourceStats.
     *
     * not supported in Firefox
     */
    mediaSourceId?: RTCMediaSourceStats['id'];
    /**
     * A floating-point value indicating the average RTCP interval
     * between two consecutive compound RTCP packets.
     */
    averageRtcpInterval?: number;
    /**
     * An integer value indicating the total number of Negative ACKnowledgement (NACK)
     * packets this RTCRtpSender has received from the remote RTCRtpReceiver.
     */
    nackCount?: number;
    /**
     * A string which identifies the RTCRemoteInboundRtpStreamStats object
     * that provides statistics for the remote peer for this same SSRC.
     * This ID is stable across multiple calls to getStats()
     */
    remoteId?: RTCRemoteInboundRtpStreamStats['id'];
    /**
     * The total number of bytes that have been retransmitted
     * for this source as of the time the statistics were sampled.
     * These retransmitted bytes comprise the packets included
     * in the value returned by retransmittedPacketsSent.
     */
    retransmittedBytesSent?: number;
    /**
     * The total number of packets that have needed to be retransmitted
     * for this source as of the time the statistics were sampled.
     * These retransmitted packets are included
     * in the value returned by packetsSent.
     */
    retransmittedPacketsSent?: number;
    /**
     * The id of the RTCAudioSenderStats or RTCVideoSenderStats
     * object containing statistics about this stream's RTCRtpSender.
     *
     * @deprecated
     */
    senderId?: string;
    /**
     * Reflects the current encoder target in bits per second.
     * The target is an instantanous value reflecting the encoder's settings,
     * but the resulting payload bytes sent per second, excluding retransmissions,
     * SHOULD closely correlate to the target. See also bytesSent and retransmittedBytesSent.
     * The targetBitrate is defined in the same way
     * as the Transport Independent Application Specific (TIAS) bitrate [RFC3890].
     *
     * not supported in Firefox
     */
    targetBitrate?: number;
    /**
     * Total number of RTP header and padding bytes sent for this SSRC.
     * This does not include the size of transport layer headers such as IP or UDP.
     * headerBytesSent + bytesSent equals the number
     * of bytes sent as payload over the transport.
     */
    headerBytesSent?: number;
    /**
     * If RTX is negotiated for retransmissions on a separate RTP stream,
     * this is the SSRC of the RTX stream that is associated with this stream's ssrc.
     * If RTX is not negotiated, this value MUST NOT be present.
     */
    rtxSsrc?: number;
    /**
     * The total number of seconds that packets have spent buffered
     * locally before being transmitted onto the network.
     * The time is measured from when a packet is emitted from the
     * RTP packetizer until it is handed over to the OS network socket.
     * This measurement is added to totalPacketSendDelay
     * when packetsSent is incremented.
     *
     * not supported in Firefox and Safari
     */
    totalPacketSendDelay?: number;
  };

type RTCSubscriberPeerConnectionStatsReading =
  RTCCommonPeerConnectionStatsReading & {
    /** tracks */
    inboundAudioTracks?: Record<
      RTCInboundRtpAudioStreamStats['ssrc'],
      RTCInboundRtpAudioStreamStats
    >;
    inboundVideoTracks?: Record<
      RTCInboundRtpVideoStreamStats['ssrc'],
      RTCInboundRtpVideoStreamStats
    >;
    remoteOutboundAudioTracks?: Record<
      RTCRemoteOutboundRtpStreamStats['ssrc'],
      RTCRemoteOutboundRtpStreamStats
    >;
    remoteOutboundVideoTracks?: Record<
      RTCRemoteOutboundRtpStreamStats['ssrc'],
      RTCRemoteOutboundRtpStreamStats
    >;
  };
type RTCSubscriberPeerConnectionStats =
  /** common stats */
  | RTCPeerConnectionStats
  | RTCAudioPlayoutStats
  | RTCCertificateStats
  | RTCIceLocalCandidateStats
  | RTCIceRemoteCandidateStats
  | RTCDataChannelStats
  | RTCCodecStats
  | RTCIceCandidatePairStats
  | RTCTransportStats
  /** only subscriber */
  | RTCInboundRtpVideoStreamStats
  | RTCInboundRtpAudioStreamStats
  | RTCRemoteOutboundRtpStreamStats;
type RTCInboundRtpVideoStreamStats = RTCInboundRtpStreamStats & {
  kind: 'video';
  mediaType: string;
  /**
   * An integer value which indicates the total number of Full Intra Request (FIR) packets
   * which this receiver has sent to the sender.
   * This is an indicator of how often the stream has lagged,
   * requiring frames to be skipped in order to catch up.
   * This value is only available for video streams.
   */
  firCount?: number;
  /**
   * A long integer value indicating the total number of frames
   * of video which have been correctly decoded so far for this media source.
   * This is the number of frames that would have been rendered
   * if none were dropped.
   * Only valid for video streams.
   */
  framesDecoded?: number;
  /**
   * It represents the total number of frames that have been rendered.
   * It is incremented just after a frame has been rendered.
   */
  framesRendered?: number;
  /**
   * It represents the total number of key frames, such as key frames
   * in VP8 [RFC6386] or IDR-frames in H.264 [RFC6184],
   * successfully decoded for this RTP media stream.
   * This is a subset of framesDecoded.
   * framesDecoded - keyFramesDecoded gives you the number of delta frames decoded.
   */
  keyFramesDecoded?: number;
  /**
   * The total number of frames dropped prior to decode or dropped
   * because the frame missed its display deadline for this receiver's track.
   * The measurement begins when the receiver is created and
   * is a cumulative metric as defined in Appendix A (g) of [RFC7004].
   */
  framesDropped?: number;
  /**
   * Represents the width of the last decoded frame.
   * Before the first frame is decoded this member MUST NOT exist.
   */
  frameWidth?: number;
  /**
   * Represents the height of the last decoded frame.
   * Before the first frame is decoded this member MUST NOT exist.
   */
  frameHeight?: number;
  /**
   *  The number of decoded frames in the last second.
   */
  framesPerSecond?: number;
  /**
   * A DOMHighResTimeStamp indicating the time at which the last packet was received for this source.
   * The timestamp property, on the other hand,
   * indicates the time at which the statistics object was generated.
   */
  lastPacketReceivedTimestamp?: DOMHighResTimeStamp;
  /**
   * An integer specifying the number of times the receiver has notified the sender
   * that some amount of encoded video data for one or more frames has been lost,
   * using Picture Loss Indication (PLI) packets.
   * This is only available for video streams.
   */
  pliCount?: number;
  /**
   * A 64-bit value containing the sum of the QP values for every frame decoded by this RTP receiver.
   * You can determine the average QP per frame by dividing this value by framesDecoded.
   * Valid only for video streams.
   */
  qpSum?: number;
  /**
   * An integer indicating the number of times the receiver sent a Slice Loss Indication (SLI) frame
   * to the sender to tell it that one or more consecutive (in terms of scan order)
   * video macroblocks have been lost or corrupted.
   * Available only for video streams.
   */
  sliCount?: number;
  /**
   * Total number of seconds that have been spent decoding the framesDecoded frames of this stream.
   * The average decode time can be calculated by dividing this value with framesDecoded.
   * The time it takes to decode one frame is the time passed between feeding the decoder
   * a frame and the decoder returning decoded data for that frame.
   */
  totalDecodeTime?: number;
  /**
   * Sum of the interframe delays in seconds between consecutively rendered frames,
   * recorded just after a frame has been rendered. The interframe delay variance
   * be calculated from totalInterFrameDelay, totalSquaredInterFrameDelay,
   * and framesRendered according to the formula:
   * (totalSquaredInterFrameDelay - totalInterFrameDelay^2/ framesRendered)/framesRendered.
   */
  totalInterFrameDelay?: number;
  /**
   * Sum of the squared interframe delays in seconds between consecutively rendered frames,
   * recorded just after a frame has been rendered. See totalInterFrameDelay
   * for details on how to calculate the interframe delay variance.
   */
  totalSquaredInterFrameDelay?: number;
  /**
   * Count the total number of video pauses experienced by this receiver.
   * Video is considered to be paused if time passed since last rendered frame exceeds 5 seconds.
   * pauseCount is incremented when a frame is rendered after such a pause.
   */
  pauseCount?: number;
  /**
   * Total duration of pauses (for definition of pause see pauseCount), in seconds.
   * This value is updated when a frame is rendered.
   */
  totalPausesDuration?: number;
  /**
   * Count the total number of video freezes experienced by this receiver.
   * It is a freeze if frame duration, which is time interval between two consecutively rendered frames,
   * is equal or exceeds Max(3 * avg_frame_duration_ms, avg_frame_duration_ms + 150),
   * where avg_frame_duration_ms is linear average of durations of last 30 rendered frames.
   */
  freezeCount?: number;
  /**
   * Total duration of rendered frames which are considered as frozen
   * (for definition of freeze see freezeCount), in seconds.
   * This value is updated when a frame is rendered.
   */
  totalFreezesDuration?: number;
  /**
   * Represents the total number of complete frames received on this RTP stream.
   * This metric is incremented when the complete frame is received.
   */
  framesReceived?: number;
  /**
   * Identifies the decoder implementation used.
   * This is useful for diagnosing interoperability issues.
   */
  decoderImplementation?: string;
  /**
   * Whether the decoder currently used is considered power efficient by the user agent.
   * This SHOULD reflect if the configuration results in hardware acceleration,
   * but the user agent MAY take other information into account when deciding
   * if the configuration is considered power efficient.
   */
  powerEfficientDecoder?: boolean;
  /**
   * It represents the total number of frames correctly decoded for this
   * RTP stream that consist of more than one RTP packet. For such frames the totalAssemblyTime is incremented.
   * The average frame assembly time can be calculated
   * by dividing the totalAssemblyTime with framesAssembledFromMultiplePackets.
   */
  framesAssembledFromMultiplePackets?: number;
  /**
   * The sum of the time, in seconds, each video frame takes from the time the first RTP packet
   * is received (reception timestamp) and to the time the last RTP packet of a frame is received.
   * Only incremented for frames consisting of more than one RTP packet.
   *
   * Given the complexities involved, the time of arrival or the reception timestamp
   * is measured as close to the network layer as possible. This metric is not incremented
   * for frames that are not decoded, i.e., framesDropped or frames that fail decoding
   * for other reasons (if any).
   * Only incremented for frames consisting of more than one RTP packet.
   */
  totalAssemblyTime?: number;
  /**
   * Represents the cumulative sum of all corruption probability measurements that
   * have been made for this SSRC, see corruptionMeasurements
   * regarding when this attribute SHOULD be present.
   */
  totalCorruptionProbability?: number;
  /**
   * Represents the cumulative sum of all corruption probability measurements
   * squared that have been made for this SSRC, see corruptionMeasurements
   * regarding when this attribute SHOULD be present.
   */
  totalSquaredCorruptionProbability?: number;
  /**
   * When the user agent is able to make a corruption probability measurement,
   * this counter is incremented for each such measurement and totalCorruptionProbability
   * and totalSquaredCorruptionProbability are aggregated with this measurement
   * and measurement squared respectively.
   * If the corruption-detection header extension is present in the RTP packets,
   * corruption probability measurements MUST be present.
   */
  corruptionMeasurements?: number;
};
type RTCInboundRtpAudioStreamStats = RTCInboundRtpStreamStats & {
  kind: 'audio';
  mediaType: string;
  /**
   * The total number of samples that have been received on this RTP stream.
   * This includes concealedSamples.
   */
  totalSamplesReceived?: number;
  /**
   * The total number of samples that are concealed samples. A concealed sample is
   * a sample that was replaced with synthesized samples generated locally before being played out.
   * Examples of samples that have to be concealed are samples from lost packets (reported in packetsLost)
   * or samples from packets that arrive too late to be played out (reported in packetsDiscarded).
   */
  concealedSamples?: number;
  /**
   * The total number of concealed samples inserted that are "silent".
   * Playing out silent samples results in silence or comfort noise.
   * This is a subset of concealedSamples.
   */
  silentConcealedSamples?: number;
  /**
   * The number of concealment events.
   * This counter increases every time a concealed sample is synthesized after a non-concealed sample.
   * That is, multiple consecutive concealed samples will increase the concealedSamples count multiple times
   * but is a single concealment event.
   */
  concealmentEvents?: number;
  /**
   * When playout is slowed down, this counter is increased by the difference between the number
   * of samples received and the number of samples played out.
   * If playout is slowed down by inserting samples,
   * this will be the number of inserted samples.
   */
  insertedSamplesForDeceleration?: number;
  /**
   * When playout is sped up, this counter is increased by the difference between the number
   * of samples received and the number of samples played out.
   * If speedup is achieved by removing samples, this will be the count of samples removed.
   */
  removedSamplesForAcceleration?: number;
  /**
   * Represents the audio level of the receiving track.
   * For audio levels of tracks attached locally, see RTCAudioSourceStats instead.
   *
   * The value is between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents silence,
   * and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov.
   *
   * The audioLevel is averaged over some small interval, using the algorithm described under totalAudioEnergy.
   * The interval used is implementation dependent.
   */
  audioLevel?: number;
  /**
   * Represents the audio energy of the receiving track.
   * For audio energy of tracks attached locally, see RTCAudioSourceStats instead.
   *
   * This value MUST be computed as follows: for each audio sample that is received (and thus counted by totalSamplesReceived),
   * add the sample's value divided by the highest-intensity encodable value,
   * squared and then multiplied by the duration of the sample in seconds.
   * In other words, duration * Math.pow(energy/maxEnergy, 2).
   *
   * This can be used to obtain a root mean square (RMS) value that uses the same units as audioLevel, as defined in [RFC6464].
   * It can be converted to these units using the formula Math.sqrt(totalAudioEnergy/totalSamplesDuration).
   * This calculation can also be performed using the differences between the values of two different getStats() calls,
   * in order to compute the average audio level over any desired time interval. In other words,
   * do Math.sqrt((energy2 - energy1)/(duration2 - duration1)).
   *
   * If multiple audio channels are used, the audio energy
   * of a sample refers to the highest energy of any channel.
   */
  totalAudioEnergy?: number;
  /**
   * Represents the audio duration of the receiving track.
   * For audio durations of tracks attached locally, see RTCAudioSourceStats instead.
   *
   * Represents the total duration in seconds of all samples that have been received
   * (and thus counted by totalSamplesReceived). Can be used with totalAudioEnergy
   * to compute an average audio level over different intervals.
   */
  totalSamplesDuration?: number;
  /**
   * If audio playout is happening, this is used to look up the corresponding RTCAudioPlayoutStats.
   */
  playoutId?: RTCAudioPlayoutStats['id'];
};
/**
 * Statistics describing the state of one
 * of the connection's inbound data streams.
 */
type RTCInboundRtpStreamStats = RTCMediaSourceStats &
  RTCRtpStreamStats &
  RTCReceivedRtpStreamStats & {
    type: 'inbound-rtp';
    /**
     * A floating-point value indicating the average RTCP interval
     * between two consecutive compound RTCP packets.
     */
    averageRtcpInterval?: number;
    /**
     * A 64-bit integer which indicates the total number
     * of bytes that have been received so far for this media source.
     */
    bytesReceived?: number;
    /**
     * An integer value indicating the number of RTP Forward Error Correction (FEC) packets
     * which have been received for this source, for which the error correction payload was discarded.
     */
    fecPacketsDiscarded?: number;
    /**
     * Total number of RTP FEC bytes received for this SSRC, only including payload bytes.
     * This is a subset of bytesReceived.
     * If a FEC mechanism that uses a different ssrc was negotiated,
     * FEC packets are sent over a separate SSRC but is still accounted for here.
     */
    fecBytesReceived?: number;
    /**
     * An integer value indicating the total number of RTP FEC packets received for this source.
     * This counter may also be incremented when FEC packets arrive in-band along with media content;
     * this can happen with Opus, for example.
     */
    fecPacketsReceived?: number;
    /**
     * An integer value indicating the total number of Negative ACKnowledgement (NACK)
     * packets this receiver has sent.
     */
    nackCount?: number;
    /**
     * An integer value indicating the total number of packets that
     * have been discarded because they were duplicates.
     * These packets are not counted by packetsDiscarded.
     */
    packetsDuplicated?: number;
    /**
     * An integer totaling the number of RTP packets that could not be decrypted.
     * These packets are not counted by packetsDiscarded.
     */
    packetsFailedDecryption?: number;
    /**
     * A record of key-value pairs with strings as the keys mapped to 32-bit integer values,
     * each indicating the total number of packets this receiver has received on this RTP stream
     * from this source for each Differentiated Services Code Point (DSCP).
     */
    perDscpPacketsReceived?: number;
    /**
     * A string indicating which identifies the RTCAudioReceiverStats or RTCVideoReceiverStats object
     * associated with the stream's receiver. This ID is stable across multiple calls to getStats().
     *
     * @deprecated
     */
    receiverId?: string;
    /**
     * A string which identifies the RTCRemoteOutboundRtpStreamStats object that provides statistics
     * for the remote peer for this same SSRC.
     * This ID is stable across multiple calls to getStats().
     */
    remoteId?: RTCRemoteOutboundRtpStreamStats['id'];
    /**
     * If the RTCRtpTransceiver owning this stream has a mid value that is not null,
     * this is that value, otherwise this member MUST NOT be present.
     */
    mid?: RTCRtpTransceiver['mid'];
    /**
     * Total number of RTP header and padding bytes received for this SSRC. This includes retransmissions.
     * This does not include the size of transport layer headers such as IP or UDP.
     * headerBytesReceived + bytesReceived equals the number of bytes received as payload over the transport.
     */
    headerBytesReceived?: number;
    /**
     * The cumulative number of RTP packets discarded by the jitter buffer due to late or early-arrival, i.e.,
     * these packets are not played out. RTP packets discarded due to packet duplication
     * are not reported in this metric [XRBLOCK-STATS]. Calculated as defined
     * in [RFC7002] section 3.2 and Appendix A.a.
     */
    packetsDiscarded?: number;
    /**
     * It is the sum of the time, in seconds, each audio sample or video frame takes from the time
     * the first RTP packet is received (reception timestamp) and to the time the corresponding sample
     * or frame is decoded (decoded timestamp). At this point the audio sample or video frame is ready
     * for playout by the MediaStreamTrack. Typically ready for playout here means after the audio sample
     * or video frame is fully decoded by the decoder.
     *
     * Given the complexities involved, the time of arrival or the reception timestamp is measured
     * as close to the network layer as possible and the decoded timestamp is measured as soon
     * as the complete sample or frame is decoded.
     *
     * In the case of audio, several samples are received in the same RTP packet,
     * all samples will share the same reception timestamp and different decoded timestamps.
     * In the case of video, the frame is received over several RTP packets,
     * in this case the earliest timestamp containing the frame is counted as the reception timestamp,
     * and the decoded timestamp corresponds to when the complete frame is decoded.
     *
     * This metric is not incremented for frames that are not decoded, i.e. framesDropped.
     * The average processing delay can be calculated by dividing the totalProcessingDelay
     * with the framesDecoded for video (or povisional stats spec totalSamplesDecoded for audio).
     */
    totalProcessingDelay?: number;
    /**
     * This is the estimated playout time of this receiver's track.
     * The playout time is the NTP timestamp of the last playable audio sample
     * or video frame that has a known timestamp (from an RTCP SR packet mapping RTP timestamps to NTP timestamps),
     * extrapolated with the time elapsed since it was ready to be played out. This is the "current time"
     * of the track in NTP clock time of the sender and can be present even
     * if there is no audio currently playing.
     *
     * This can be useful for estimating how much audio and video is out of sync for two tracks from the same source,
     * audioInboundRtpStats.estimatedPlayoutTimestamp - videoInboundRtpStats.estimatedPlayoutTimestamp.
     */
    estimatedPlayoutTimestamp?: DOMHighResTimeStamp;
    /**
     * The purpose of the jitter buffer is to recombine RTP packets into frames (in the case of video) and have smooth playout.
     * The model described here assumes that the samples or frames are still compressed and have not yet been decoded.
     * It is the sum of the time, in seconds, each audio sample or a video frame takes from the time the first packet
     * is received by the jitter buffer (ingest timestamp) to the time it exits the jitter buffer (emit timestamp).
     * In the case of audio, several samples belong to the same RTP packet, hence they will have the same ingest timestamp
     * but different jitter buffer emit timestamps. In the case of video, the frame maybe is received over several RTP packets,
     * hence the ingest timestamp is the earliest packet of the frame that entered the jitter buffer and the emit timestamp
     * is when the whole frame exits the jitter buffer. This metric increases upon samples or frames exiting,
     * having completed their time in the buffer (and incrementing jitterBufferEmittedCount).
     * The average jitter buffer delay can be calculated by dividing the jitterBufferDelay with the jitterBufferEmittedCount.
     */
    jitterBufferDelay?: number;
    /**
     * This value is increased by the target jitter buffer delay every time a sample is emitted by the jitter buffer.
     * The added target is the target delay, in seconds, at the time that the sample was emitted from the jitter buffer.
     * To get the average target delay, divide by jitterBufferEmittedCount.
     */
    jitterBufferTargetDelay?: number;
    /**
     * The total number of audio samples or video frames that have come
     * out of the jitter buffer (increasing jitterBufferDelay).
     */
    jitterBufferEmittedCount?: number;
    /**
     * There are various reasons why the jitter buffer delay might be increased to a higher value,
     * such as to achieve AV synchronization or because a jitterBufferTarget was set on a RTCRtpReceiver.
     * When using one of these mechanisms, it can be useful to keep track of the minimal jitter buffer delay
     * that could have been achieved, so WebRTC clients can track the amount of additional delay that is being added.
     *
     * This metric works the same way as jitterBufferTargetDelay, except that it is not affected by external mechanisms
     * that increase the jitter buffer target delay, such as jitterBufferTarget (see link above), AV sync, or any other mechanisms.
     * This metric is purely based on the network characteristics such as jitter and packet loss, and can be seen
     * as the minimum obtainable jitter buffer delay if no external factors would affect it.
     * The metric is updated every time jitterBufferEmittedCount is updated.
     */
    jitterBufferMinimumDelay?: number;
    /**
     * The total number of retransmitted packets that were received for this SSRC. This is a subset of packetsReceived.
     * If RTX is not negotiated, retransmitted packets can not be identified and this member MUST NOT exist.
     */
    retransmittedPacketsReceived?: number;
    /**
     * The total number of retransmitted bytes that were received for this SSRC, only including payload bytes.
     * This is a subset of bytesReceived.
     * If RTX is not negotiated, retransmitted packets can not be identified and this member MUST NOT exist.
     */
    retransmittedBytesReceived?: number;
    /**
     * If RTX is negotiated for retransmissions on a separate RTP stream,
     * this is the SSRC of the RTX stream that is associated with this stream's ssrc.
     * If RTX is not negotiated, this value MUST NOT be present.
     */
    rtxSsrc?: number;
    /**
     * If a FEC mechanism that uses a separate RTP stream is negotiated,
     * this is the SSRC of the FEC stream that is associated with this stream's ssrc.
     * If FEC is not negotiated or uses the same RTP stream, this value MUST NOT be present.
     */
    fecSsrc?: number;
  };
/**
 * Statistics describing the state of the outbound data stream from the perspective of the remote peer.
 */
type RTCRemoteOutboundRtpStreamStats = RTCSentRtpStreamStats & {
  type: 'remote-outbound-rtp';
  /**
   * A string which is used to find the local RTCInboundRtpStreamStats
   * object that shares the same synchronization source (SSRC).
   *
   * not Supported in Safari
   */
  localId?: RTCInboundRtpStreamStats['id'];
  /**
   * A DOMHighResTimeStamp specifying the timestamp (on the remote device)
   * at which the statistics in the RTCRemoteOutboundRtpStreamStats object were sent by the remote endpoint.
   * This is different from the timestamp; it represents the time at which the object's statistics were received
   * or generated by the local endpoint.
   *
   * not Supported in Safari
   */
  remoteTimestamp?: DOMHighResTimeStamp;
  /**
   * A positive integer indicating the total number of RTCP Sender Report (SR)
   * blocks sent for this synchronization source (SSRC).
   *
   * not Supported in Firefox and Safari
   *
   * Experimental
   */
  reportsSent?: number;
  /**
   * A positive number that represents the total number of valid round trip time
   * measurements received for this synchronization source (SSRC).
   *
   * not Supported in Firefox and Safari
   *
   * Experimental
   */
  roundTripTimeMeasurements?: number;
  /**
   * A number indicating the cumulative sum of all round trip time measurements since
   * the beginning of the session, in seconds.
   * The average round trip time can be computed
   * by dividing totalRoundTripTime by roundTripTimeMeasurements.
   *
   * not Supported in Firefox and Safari
   *
   * Experimental
   */
  totalRoundTripTime?: number;
};

type RTCCommonPeerConnectionStatsBandWidth = {
  upload?: number;
  download?: number;
};
type RTCPacketsStats = {
  packetsTotal: number;
  packetsTotalDiff: number;
  packetsLost: number;
  packetsLostDiff: number;
};
type RTCIceLocalCandidateStatsMapped = RTCIceLocalCandidateStats & {
  mappedAddress?: string;
};
type RTCIceRemoteCandidateStatsMapped = RTCIceRemoteCandidateStats & {
  mappedAddress?: string;
};
type RTCCommonPeerConnectionStatsMapped = {
  mediaPlayout?: RTCPublisherPeerConnectionStatsReading['mediaPlayout'];
  peerConnection?: RTCPublisherPeerConnectionStatsReading['peerConnection'];
  codecs?: RTCPublisherPeerConnectionStatsReading['codecs'];
  transport?: RTCPublisherPeerConnectionStatsReading['transport'];
  dataChannels?: RTCPublisherPeerConnectionStatsReading['dataChannels'];
  candidatePairs?: RTCPublisherPeerConnectionStatsReading['candidatePairs'];
  activeCandidatePair?: RTCIceCandidatePairStats;
  bandWidth?: RTCCommonPeerConnectionStatsBandWidth;
  localCandidates?: RTCPublisherPeerConnectionStatsReading['localCandidates'];
  localCandidate?: RTCIceLocalCandidateStatsMapped;
  remoteCandidates?: RTCPublisherPeerConnectionStatsReading['remoteCandidates'];
  remoteCandidate?: RTCIceRemoteCandidateStatsMapped;
  certificates?: RTCPublisherPeerConnectionStatsReading['certificates'];
  localCertificate?: RTCCertificateStats;
  remoteCertificate?: RTCCertificateStats;
};

type RTCPublisherPeerConnectionStatsMapped =
  RTCCommonPeerConnectionStatsMapped & {
    audioTracks?: RTCPublisherPeerConnectionStatsAudioTracksMapped;
    /**
     * for only Firefox
     * Firefox not have RTCOutboundRtpAudioStreamStats['mediaSourceId']
     * for mapped data to audioTracks
     */
    mediaSourceAudioTracks?: RTCAudioSourceStatsMapped;
    videoTracks?: RTCPublisherPeerConnectionStatsVideoTracksMapped;
    /**
     * for only Firefox
     * Firefox not have RTCOutboundRtpVideoStreamStats['mediaSourceId']
     * for mapped data to videoTracks
     */
    mediaSourceVideoTracks?: RTCVideoSourceStatsMapped;
    uploadBitrateAudio?: number;
    uploadBitrateVideo?: number;
    uploadBitrate?: number;
    packetsSendAudio?: number;
    packetsSendAudioDiff?: number;
    packetsSendVideo?: number;
    packetsSendVideoDiff?: number;
    packetsSend?: number;
    packetsSendDiff?: number;
    packetsLostAudio?: number;
    packetsLostAudioDiff?: number;
    packetsLostVideo?: number;
    packetsLostVideoDiff?: number;
    packetsLost?: number;
    packetsLostDiff?: number;
    maxRttAudio?: number;
    maxRttVideo?: number;
    maxRtt?: number;
    maxJitterAudio?: number;
    maxJitterVideo?: number;
    maxJitter?: number;
  };
type RTCPublisherPeerConnectionStatsAudioTrackMapped =
  RTCPublisherPeerConnectionStatsTrackMapped & {
    mediaSource?: RTCAudioSourceStats;
    outbound?: RTCOutboundRtpAudioStreamStats;
    remoteInbound?: RTCRemoteInboundRtpAudioStreamStats;
  };
type RTCPublisherPeerConnectionStatsAudioTracksMapped = Record<
  RTCRemoteInboundRtpAudioStreamStats['ssrc'],
  RTCPublisherPeerConnectionStatsAudioTrackMapped
>;
/**
 * for only Firefox
 * Firefox not have RTCOutboundRtpAudioStreamStats['mediaSourceId']
 * for mapped data to audioTracks
 */
type RTCAudioSourceStatsMapped = Record<
  RTCAudioSourceStats['trackIdentifier'],
  RTCAudioSourceStats
>;
type RTCPublisherPeerConnectionStatsVideoTrackMapped =
  RTCPublisherPeerConnectionStatsTrackMapped & {
    mediaSource?: RTCVideoSourceStats;
    outbound?: RTCOutboundRtpVideoStreamStats;
    remoteInbound?: RTCRemoteInboundRtpVideoStreamStats;
    fps?: number;
  };
type RTCPublisherPeerConnectionStatsVideoTracksMapped = Record<
  RTCRemoteInboundRtpVideoStreamStats['ssrc'],
  RTCPublisherPeerConnectionStatsVideoTrackMapped
>;
/**
 * for only Firefox
 * Firefox not have RTCOutboundRtpVideoStreamStats['mediaSourceId']
 * for mapped data to videoTracks
 */
type RTCVideoSourceStatsMapped = Record<
  RTCVideoSourceStats['trackIdentifier'],
  RTCVideoSourceStats
>;
type RTCPublisherPeerConnectionStatsTrackMapped = {
  codec?: RTCCodecStats;
  uploadBitrate?: number;
  packetsSend?: number;
  packetsSendDiff?: number;
  packetsLost?: number;
  packetsLostDiff?: number;
  rtt?: number;
  jitter?: number;
  avgPacketSendDelay?: number;
};

type RTCSubscriberPeerConnectionStatsMapped =
  RTCCommonPeerConnectionStatsMapped & {
    audioTracks?: RTCSubscriberPeerConnectionStatsAudioTracksMapped;
    videoTracks?: RTCSubscriberPeerConnectionStatsVideoTracksMapped;
    downloadAudioBitrate?: number;
    downloadVideoBitrate?: number;
    downloadBitrate?: number;
    packetsReceivedAudio?: number;
    packetsReceivedAudioDiff?: number;
    packetsReceivedVideo?: number;
    packetsReceivedVideoDiff?: number;
    packetsReceived?: number;
    packetsReceivedDiff?: number;
    packetsLostAudio?: number;
    packetsLostAudioDiff?: number;
    packetsLostVideo?: number;
    packetsLostVideoDiff?: number;
    packetsLost?: number;
    packetsLostDiff?: number;
    maxRttAudio?: number;
    maxRttVideo?: number;
    maxRtt?: number;
    maxJitterAudio?: number;
    maxJitterVideo?: number;
    maxJitter?: number;
    avgPlayoutDelay?: number;
  };
type RTCSubscriberPeerConnectionStatsAudioTrackMapped =
  RTCSubscriberPeerConnectionStatsTrackMapped & {
    inbound?: RTCInboundRtpAudioStreamStats;
    remoteOutbound?: RTCRemoteOutboundRtpStreamStats;
  };
type RTCSubscriberPeerConnectionStatsAudioTracksMapped = Record<
  RTCInboundRtpAudioStreamStats['ssrc'],
  RTCSubscriberPeerConnectionStatsAudioTrackMapped
>;
type RTCSubscriberPeerConnectionStatsVideoTrackMapped =
  RTCSubscriberPeerConnectionStatsTrackMapped & {
    inbound?: RTCInboundRtpVideoStreamStats;
    remoteOutbound?: RTCRemoteOutboundRtpStreamStats;
  };
type RTCSubscriberPeerConnectionStatsTrackMapped = {
  codec?: RTCCodecStats;
  downloadBitrate?: number;
  packetsReceived?: number;
  packetsReceivedDiff?: number;
  packetsLost?: number;
  packetsLostDiff?: number;
  rtt?: number;
  jitter?: number;
  avgProcessingDelay?: number;
  avgJitterBufferDelay?: number;
};
type RTCSubscriberPeerConnectionStatsVideoTracksMapped = Record<
  RTCInboundRtpVideoStreamStats['ssrc'],
  RTCSubscriberPeerConnectionStatsVideoTrackMapped
>;

type WebRTCMetricsControllerService = {
  getPublisherTrackStats: <
    MEDIA_TYPE extends MediaType,
    RESULT extends MEDIA_TYPE extends 'audio'
      ? RTCPublisherPeerConnectionStatsAudioTrackMapped
      : RTCPublisherPeerConnectionStatsVideoTrackMapped,
  >(
    mediaType: MEDIA_TYPE,
  ) => RESULT | RESULT[] | undefined;
  getSubscriberTrackStats: <
    MEDIA_TYPE extends MediaType,
    RESULT extends MEDIA_TYPE extends 'audio'
      ? RTCSubscriberPeerConnectionStatsAudioTrackMapped
      : RTCSubscriberPeerConnectionStatsVideoTrackMapped,
  >(
    participantId: JazzRoomParticipantId,
    mediaType: MEDIA_TYPE,
  ) => RESULT | undefined;
  collectClientMetrics: () => Promise<WebRTCMetricsCollected>;
};
type WebRTCMetricsCollected = {
  publisher?: RTCPublisherPeerConnectionStatsMapped;
  subscriber?: RTCSubscriberPeerConnectionStatsMapped;
};
type WebRTCMetricsEvent = {
  /**
   * события отправки сырой статистики
   */
  pcPublisherInitMetrics: {
    stats: RTCStatsReport;
  };
  pcSubscriberInitMetrics: {
    stats: RTCStatsReport;
  };
  /**
   * события отправки распарсеной статистики
   */
  pcPublisherMetrics: {
    stats: RTCPublisherPeerConnectionStatsMapped;
  };
  pcSubscriberMetrics: {
    stats: RTCSubscriberPeerConnectionStatsMapped;
  };
  /**
   * событие времени старта медийки
   *
   * @deprecated use collectMetricsPlugin event client.jn.latency
   * */
  mediaStartPerformance: MediaStartPerformance;
  /**
   * на сервер были отправлены первые аудио пакеты
   */
  publisherSendFirstAudioPackage: undefined;
  /**
   * на сервер были отправлены первые видео пакеты
   */
  publisherSendFirstVideoPackage: undefined;
};
type MediaStartPerformance = {
  roomConnected: number;
  transportConnected: number;
  mediaSessionTime: number;
  iceConnected: number;
};
/**
 * A service for collecting media statistics from PeerConnection.
 * It collects metrics for publisher and subscriber separately.
 * Metrics can be obtained by subscribing to events.
 */
type WebRTCMetricsService = {
  publisherStats: Atom<RTCPublisherPeerConnectionStatsMapped | undefined>;
  subscriberStats: Atom<RTCSubscriberPeerConnectionStatsMapped | undefined>;
  /**
   * @deprecated use collectMetricsPlugin event client.jn.latency
   */
  mediaStartPerformance: Atom<Partial<MediaStartPerformance>>;
  on: TransportRoot<WebRTCMetricsEvent>['on'];
  once: TransportRoot<WebRTCMetricsEvent>['once'];
  off: TransportRoot<WebRTCMetricsEvent>['off'];
  startCollectMetrics: () => void;
  stopCollectMetrics: () => void;
  collectClientMetrics: WebRTCMetricsControllerService['collectClientMetrics'];
  getPublisherTrackStats: WebRTCMetricsControllerService['getPublisherTrackStats'];
  getSubscriberTrackStats: WebRTCMetricsControllerService['getSubscriberTrackStats'];
};

declare function getMediaMetricsService(room: JazzRoom): WebRTCMetricsService;
declare function getConnectionQualityService(
  room: JazzRoom,
): ConnectionQualityService;

type JazzLobbyConnectingStatus = 'connecting';
type JazzLobbyConnectedStatus = 'connected';
type JazzLobbyDisconnectingStatus = 'disconnecting';
type JazzLobbyDisconnectedStatus = 'disconnected';
type JazzLobbyErrorStatus = 'error';
type JazzLobbyStatus =
  | JazzLobbyConnectingStatus
  | JazzLobbyConnectedStatus
  | JazzLobbyDisconnectingStatus
  | JazzLobbyDisconnectedStatus
  | JazzLobbyErrorStatus;
type AccessDeniedError = {
  type: 'accessDenied';
};
type JazzLobbyErrorReason = AccessDeniedError | UnknownError;
type JazzLobbyParticipantsEvent = {
  type: 'participants';
  payload: {
    participants: JazzLobbyParticipant[];
  };
};
type JazzLobbyEventParticipantJoined = {
  type: 'participantJoined';
  payload: {
    participant: JazzLobbyParticipant;
  };
};
type JazzLobbyEventParticipantLeft = {
  type: 'participantLeft';
  payload: {
    participant: JazzLobbyParticipant;
  };
};
type JazzLobbyNameUpdatedEvent = {
  type: 'participantNameUpdated';
  payload: {
    participant: JazzLobbyParticipant;
  };
};
type JazzLobbyEventAccessDenied = {
  type: 'accessDenied';
};
type JazzLobbyEventAccessGranted = {
  type: 'accessGranted';
};
type JazzLobbyEventConnecting = {
  type: 'connecting';
};
type JazzLobbyEventConnected = {
  type: 'connected';
};
type JazzLobbyEventDisconnecting = {
  type: 'disconnecting';
};
type JazzLobbyEventDisconnected = {
  type: 'disconnected';
};
type JazzLobbyEventError = {
  type: 'error';
  payload: {
    error: JazzLobbyErrorReason;
  };
};
type JazzLobbyEventSettingsChanged = {
  type: 'settingsChanged';
  payload: JazzLobbySettingsChangedEventPayload;
};
type JazzLobbySettingsChangedEventPayload = Partial<JazzLobbySettings>;
type JazzLobbyModeratorJoinedEvent = {
  type: 'moderatorJoined';
  payload: {
    hasModerator: true;
  };
};
type JazzLobbyModeratorLeftEvent = {
  type: 'moderatorLeft';
  payload: {
    hasModerator: false;
  };
};
type JazzLobbyPermissionsChangedEvent = {
  type: 'permissionsChanged';
  payload: JazzLobbyPermissionUpdate;
};
type JazzLobbyEventStatusChanged = {
  type: 'statusChanged';
  payload:
    | {
        status: JazzLobbyConnectingStatus;
      }
    | {
        status: JazzLobbyConnectedStatus;
      }
    | {
        status: JazzLobbyDisconnectingStatus;
      }
    | {
        status: JazzLobbyDisconnectedStatus;
      }
    | {
        status: JazzLobbyErrorStatus;
        error: JazzLobbyErrorReason;
      };
};
type JazzLobbyEvent =
  | JazzLobbyParticipantsEvent
  | JazzLobbyNameUpdatedEvent
  | JazzLobbyEventParticipantJoined
  | JazzLobbyEventParticipantLeft
  | JazzLobbyEventAccessDenied
  | JazzLobbyEventAccessGranted
  | JazzLobbyEventConnecting
  | JazzLobbyEventConnected
  | JazzLobbyEventDisconnecting
  | JazzLobbyEventDisconnected
  | JazzLobbyEventError
  | JazzLobbyEventStatusChanged
  | JazzLobbyEventSettingsChanged
  | JazzLobbyModeratorJoinedEvent
  | JazzLobbyModeratorLeftEvent
  | JazzLobbyPermissionsChangedEvent;
type JazzLobbyEvents = EventToMap<JazzLobbyEvent>;
type JazzLobbyParticipantId = string;
type JazzLobbyParticipant = Readonly<{
  id: JazzLobbyParticipantId;
  userName: string;
}>;
type JazzLobbyModerator = Readonly<{
  denyAccess: (
    participantIds:
      | ReadonlyArray<JazzLobbyParticipantId>
      | JazzLobbyParticipantId,
  ) => void;
  denyAccessAll: () => void;
  approveAccess: (
    participantIds:
      | ReadonlyArray<JazzLobbyParticipantId>
      | JazzLobbyParticipantId,
  ) => void;
  approveAccessAll: () => void;
  /**
   * @deprecated
   * use denyAccess
   */
  kickUsers: (
    participantIds:
      | ReadonlyArray<JazzLobbyParticipantId>
      | JazzLobbyParticipantId,
  ) => void;
  /**
   * @deprecated
   * use denyAccessAll
   */
  kickUsersAll: () => void;
  setSettings: (settings: JazzLobbySettingsUpdate) => Promise<void>;
}>;
type JazzLobby = Readonly<{
  settings: JazzLobbySettingsQueries;
  status: QueryAtom<JazzLobbyStatus>;
  permissions: JazzLobbyPermissionsState;
  ready: (
    status?: 'connected' | 'disconnecting' | 'disconnected',
  ) => Promise<void>;
  error: QueryAtom<JazzLobbyErrorReason | undefined>;
  participants: QueryAtom<JazzLobbyParticipant[]>;
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<JazzLobbyEvent>;
  on: TransportRoot<JazzLobbyEvents>['on'];
  once: TransportRoot<JazzLobbyEvents>['once'];
  off: TransportRoot<JazzLobbyEvents>['off'];
  moderator: JazzLobbyModerator;
  hasModerator: QueryAtom<boolean>;
}>;
type JazzLobbySettings = {
  isLobbyEnabled: boolean;
  title: string;
};
type JazzLobbySettingsQueries = {
  isLobbyEnabled: QueryAtom<boolean | undefined>;
  title: QueryAtom<string | undefined>;
};
type JazzLobbyPermissionsState = {
  canManageLobby: QueryAtom<boolean | undefined>;
};
type JazzLobbySettingsUpdate = {
  isLobbyEnabled?: boolean;
};
type JazzLobbyPermissions = {
  canManageLobby: boolean;
};
type JazzLobbyPermissionUpdate = Partial<JazzLobbyPermissions>;

declare function lobbyPlugin(): JazzSdkPlugin;

declare const getLobby: <C extends JazzRoomExtender[]>(
  jazzRoom: JazzRoom<C>,
) => JazzLobby;

declare class JazzLobbyError<
  T extends JazzLobbyErrorReason = JazzLobbyErrorReason,
> extends Error {
  readonly reason: T;
  constructor(message: string, reason: T);
}

declare const LOBBY_CONNECTING_STATUS: JazzLobbyConnectingStatus;
declare const LOBBY_CONNECTED_STATUS: JazzLobbyConnectedStatus;
declare const LOBBY_DISCONNECTING_STATUS: JazzLobbyDisconnectingStatus;
declare const LOBBY_DISCONNECTED_STATUS: JazzLobbyDisconnectedStatus;
declare const LOBBY_ERROR_STATUS: JazzLobbyErrorStatus;

declare function activityPlugin(): JazzSdkPlugin;

type JazzReactionType = ReactionType;
type JazzParticipantReaction = Readonly<{
  timestamp: Timestamp;
  participantId: JazzRoomParticipantId;
  reaction: JazzReactionType;
  code: string;
}>;
type JazzActivityEventRaiseHand = Readonly<{
  type: 'raiseHand';
  payload: {
    participantId: JazzRoomParticipantId;
  };
}>;
type JazzActivityEventReleaseHand = Readonly<{
  type: 'releaseHand';
  payload: {
    participantId: JazzRoomParticipantId;
  };
}>;
type JazzActivityEventReaction = Readonly<{
  type: 'reaction';
  payload: JazzParticipantReaction;
}>;
type JazzActivityEvent =
  | JazzActivityEventRaiseHand
  | JazzActivityEventReleaseHand
  | JazzActivityEventReaction;
type JazzActivityEvents = EventToMap<JazzActivityEvent>;
type JazzActivity = {
  handsRaised: Atom<ReadonlySet<JazzRoomParticipantId>>;
  getHandRaised: (participantId: JazzRoomParticipantId) => Atom<boolean>;
  raiseHand: (isRaised: boolean) => void;
  setReaction: (reaction: JazzReactionType) => void;
  /**
   * @deprecated use on, off, once
   */
  event$: Observable<JazzActivityEvent>;
  on: TransportRoot<JazzActivityEvents>['on'];
  once: TransportRoot<JazzActivityEvents>['once'];
  off: TransportRoot<JazzActivityEvents>['off'];
};

declare function getActivity<R extends JazzRoomExtender[]>(
  room: JazzRoom<R>,
): JazzActivity;

declare const SDK_VERSION: string;

/**
 * Creates Jazz SDK for web applications.
 */
declare function createJazzSdk(options: JazzSdkOptions): Promise<JazzSdk>;

declare function getJazzSdk<R extends JazzRoomExtender[]>(
  value: JazzRoomConnection | JazzRoom<R> | JazzClient,
): JazzSdk;

/**
 * Этот тип создает полную копию другого типа T, предотвращая отображение ссылки на исходный тип.
 * Используется техника Omit<T, ''>, чтобы заставить TypeScript считать новый тип уникальным,
 * хотя технически никаких изменений в структуре самого типа не производится.
 */
type CopyType<T> = Omit<T, ''>;

declare class ParticipantPermissionError extends Error {
  permission: string;
  participantId: string;
  constructor(permission: string, participantId: string, message?: string);
}

/**
 * Creates Jazz SDK for web applications.
 *
 */
declare function createJazzSdkWeb(options?: JazzSdkOptions): Promise<JazzSdk>;
/**
 * Creates Jazz SDK for web applications.
 * @description use createJazzSdkWeb
 */
declare const createJazzWebSdk: typeof createJazzSdkWeb;

export {
  type AccessByPermissionError,
  type AccessDeniedError,
  type AnyObject,
  type AudioInputOptions,
  AuthorizationRequiredError,
  type CollectMetricsHandler,
  type CollectMetricsMeta,
  type CollectMetricsMetaActions,
  type CollectMetricsMetric,
  type CollectMetricsMetricData,
  type ConnectionQualities,
  type ConnectionQuality,
  type ConnectionQualityEvents,
  type ConnectionQualityName,
  type ConnectionQualityService,
  type ConnectionStatus,
  type CopyType,
  DISPLAY_MEDIA_TYPE,
  type DeepUnion,
  type DeepUnionAll,
  DeniedBySystemError,
  DevicesNotFoundError,
  type DisplayCaptureMode,
  type DisplayEndpointsService,
  type DisplayInputOptions,
  type DisplayMediaPermissionState,
  type DisplayMediaType,
  DisplayPermissionDeniedError,
  type EventError,
  type EventOk,
  type EventToMap,
  type Extender,
  type ForbiddenError,
  type GetMeetingHistoryListParams,
  type GetSelectedAudioInputOptions,
  type GetSelectedVideoInputOptions,
  HttpClientFetchError,
  HttpClientResponseError,
  IncorrectServerUrlError,
  LOBBY_CONNECTED_STATUS as JAZZ_LOBBY_CONNECTED_STATUS,
  LOBBY_CONNECTING_STATUS as JAZZ_LOBBY_CONNECTING_STATUS,
  LOBBY_DISCONNECTED_STATUS as JAZZ_LOBBY_DISCONNECTED_STATUS,
  LOBBY_DISCONNECTING_STATUS as JAZZ_LOBBY_DISCONNECTING_STATUS,
  LOBBY_ERROR_STATUS as JAZZ_LOBBY_ERROR_STATUS,
  type JazzActivity,
  type JazzActivityEvent,
  type JazzActivityEventRaiseHand,
  type JazzActivityEventReaction,
  type JazzActivityEventReleaseHand,
  type JazzClient,
  type JazzClientCloseParams,
  type JazzClientEvent,
  type JazzClientEventAddRoom,
  type JazzClientEventAddRoomConnection,
  type JazzClientEventDestroy,
  type JazzClientEventRemoveRoom,
  type JazzClientEventRemoveRoomConnection,
  type JazzClientEvents,
  type JazzClientExtender,
  type JazzClientJoinParams,
  type JazzClientJoinWarmUpParams,
  type JazzClientOptions,
  type JazzClientUpdateParams,
  type JazzLobby,
  JazzLobbyError,
  type JazzLobbyErrorReason,
  type JazzLobbyEvent,
  type JazzLobbyEventAccessDenied,
  type JazzLobbyEventAccessGranted,
  type JazzLobbyEventConnected,
  type JazzLobbyEventConnecting,
  type JazzLobbyEventDisconnected,
  type JazzLobbyEventDisconnecting,
  type JazzLobbyEventError,
  type JazzLobbyEventParticipantJoined,
  type JazzLobbyEventParticipantLeft,
  type JazzLobbyEventSettingsChanged,
  type JazzLobbyEventStatusChanged,
  type JazzLobbyModerator,
  type JazzLobbyParticipant,
  type JazzLobbyParticipantId,
  type JazzLobbySettings,
  type JazzLobbySettingsQueries,
  type JazzLobbySettingsUpdate,
  type JazzLobbyStatus,
  type JazzMeetingId,
  type JazzParticipantReaction,
  type JazzReactionType,
  type JazzRoom,
  type JazzRoomAudioSource,
  type JazzRoomAudioSourceState,
  type JazzRoomConferenceId,
  type JazzRoomConnectionStatus,
  JazzRoomError,
  type JazzRoomErrorReason,
  type JazzRoomEvent,
  type JazzRoomEventAccessByPermission,
  type JazzRoomEventAddTrack,
  type JazzRoomEventConnected,
  type JazzRoomEventConnecting,
  type JazzRoomEventConnectionChanged,
  type JazzRoomEventConnectionConnecting,
  type JazzRoomEventConnectionDisconnected,
  type JazzRoomEventConnectionFailed,
  type JazzRoomEventConnectionInterrupted,
  type JazzRoomEventConnectionOpen,
  type JazzRoomEventDestroy,
  type JazzRoomEventDisconnected,
  type JazzRoomEventDisconnecting,
  type JazzRoomEventDominantSpeakerChanged,
  type JazzRoomEventDominantSpeakerLeft,
  type JazzRoomEventError,
  type JazzRoomEventKicked,
  type JazzRoomEventLeave,
  type JazzRoomEventLocalParticipantChanged,
  type JazzRoomEventParamsChanged,
  type JazzRoomEventParticipantJoined,
  type JazzRoomEventParticipantLeft,
  type JazzRoomEventParticipantUpdate,
  type JazzRoomEventParticipants,
  type JazzRoomEventPermissionDenied,
  type JazzRoomEventPermissionGranted,
  type JazzRoomEventPermissionRequested,
  type JazzRoomEventReconnecting,
  type JazzRoomEventRemoteTrackInfo,
  type JazzRoomEventRemoveTrack,
  type JazzRoomEventRolePermissionsChanged,
  type JazzRoomEventSettingsChanged,
  type JazzRoomEventStatusChanged,
  type JazzRoomEventTrackAddRejected,
  type JazzRoomEventTrackMuteChangeRejected,
  type JazzRoomEventTrackMuteChanged,
  type JazzRoomEventTrackUpdated,
  type JazzRoomEvents,
  type JazzRoomExtender,
  type JazzRoomGrantedPermissions,
  type JazzRoomId,
  type JazzRoomKickedReason,
  type JazzRoomLeaveReason,
  type JazzRoomMediaSourceState,
  type JazzRoomParams,
  type JazzRoomParamsUpdate,
  type JazzRoomPartialUserPermissions,
  type JazzRoomParticipant,
  type JazzRoomParticipantBot,
  type JazzRoomParticipantBotType,
  type JazzRoomParticipantId,
  type JazzRoomParticipantRole,
  type JazzRoomParticipantUser,
  type JazzRoomPermissionRequest,
  type JazzRoomPermissionRequestResolution,
  type JazzRoomPermissionRequestResolutions,
  type JazzRoomPermissionRequests,
  type JazzRoomQuality,
  type JazzRoomReconnectingReason,
  type JazzRoomRolePermissions,
  type JazzRoomSettings,
  type JazzRoomSettingsQueries,
  type JazzRoomSettingsUpdate,
  type JazzRoomSources,
  type JazzRoomStatus,
  type JazzRoomStatusMap,
  type JazzRoomType,
  type JazzRoomUserPermissionKey,
  type JazzRoomUserPermissionRequest,
  type JazzRoomUserPermissionRequestKey,
  type JazzRoomUserPermissionRequests,
  type JazzRoomUserPermissions,
  type JazzRoomVideoQuality,
  type JazzRoomVideoRequest,
  type JazzRoomVideoSource,
  type JazzRoomVideoSourceState,
  type JazzRoomWarmUp,
  type JazzSdk,
  type JazzSdkAdditionalPlugins,
  type JazzSdkAuthEvent,
  type JazzSdkAuthMethod,
  type JazzSdkAuthService,
  type JazzSdkAuthStatus,
  type JazzSdkConferenceManager,
  type JazzSdkConferenceRoomDetails,
  type JazzSdkCreateAnonymousRoomDetails,
  type JazzSdkCreateAnonymousRoomError,
  type JazzSdkCreateAnonymousRoomParams,
  type JazzSdkCreateAnonymousRoomResult,
  type JazzSdkCreateConferenceDetails,
  type JazzSdkCreateConferenceError,
  type JazzSdkCreateConferenceParams,
  type JazzSdkCreateConferenceResult,
  type JazzSdkEvent,
  type JazzSdkEventAddClient,
  type JazzSdkEventAddRoom,
  type JazzSdkEventAddRoomConnection,
  type JazzSdkEventRemoveClient,
  type JazzSdkEventRemoveRoom,
  type JazzSdkEventRemoveRoomConnection,
  type JazzSdkEvents,
  type JazzSdkGetRoomDetailsError,
  type JazzSdkModule,
  type JazzSdkModuleDeclaration,
  type JazzSdkModuleFactory,
  type JazzSdkModuleFactoryProps,
  type JazzSdkOptions,
  type JazzSdkPlugin,
  type JazzSdkRoomDetails,
  type JazzSdkRoomDetailsParams,
  type JazzSdkUserInfo,
  type JazzSdkUserInfoAuthError,
  type JazzSdkUserInfoAuthType,
  type JazzSdkUserInfoServerFeatures,
  type JazzVideoResolution$1 as JazzVideoResolution,
  type JoinWarmUp,
  LOCAL_MEDIA_DEVICE_KIND,
  type LocalAudioInputDevice,
  type LocalAudioOutputDevice,
  type LocalDevicesEvent,
  type LocalDevicesEventAddTrack,
  type LocalDevicesEventAudioAGCChanged,
  type LocalDevicesEventAudioInputChanged,
  type LocalDevicesEventAudioOutputChanged,
  type LocalDevicesEventDisposeTrack,
  type LocalDevicesEventErrorDevicePermissions,
  type LocalDevicesEventLocalTrackUpdated,
  type LocalDevicesEventMediaDevicesChanged,
  type LocalDevicesEventMuteTrackChanged,
  type LocalDevicesEventPermissionsChanged,
  type LocalDevicesEventRemoveTrack,
  type LocalDevicesEventRequestDevicePermissions,
  type LocalDevicesEventSuccessDevicePermissions,
  type LocalDevicesEventVideoInputChanged,
  type LocalDevicesEvents,
  type LocalDevicesManager,
  type LocalDevicesMediaStreamState,
  type LocalMediaDevice,
  type LocalMediaDeviceId,
  type LocalMediaDeviceKind,
  type LocalMediaDevicesEvents,
  type LocalTrackEffect,
  type LocalVideoInputDevice,
  type LogEvent,
  type LogLevel,
  MEDIA_PERMISSION,
  type MakeExtender,
  type MaxMeetingCountExceededError,
  type MediaMetricsPluginOptions,
  type MediaMetricsPluginSettings,
  type MediaPermission,
  type MediaPermissionErrorKind,
  type MediaPermissionErrorType,
  type MediaStartPerformance,
  type MediaType,
  type MeetingHistoryListResult,
  type NetworkError,
  type NotAllowedError,
  NotReadableError,
  type OpenConnectionError,
  OrderDisplayTrackError,
  ParticipantPermissionError,
  PermissionDeniedError,
  type PowerProfilePluginCPUEvents,
  type PowerProfilePluginCPUUsages,
  type PowerProfilePluginMediaDegradationReason,
  type PowerProfilePluginService,
  type PropertyExtender,
  type Query$1 as Query,
  type QueryAtom,
  type RTCAudioPlayoutStats,
  type RTCAudioSourceStats,
  type RTCAudioSourceStatsMapped,
  type RTCCertificateStats,
  type RTCCodecStats,
  type RTCCommonPeerConnectionStatsBandWidth,
  type RTCCommonPeerConnectionStatsMapped,
  type RTCCommonPeerConnectionStatsReading,
  type RTCCommonStats,
  type RTCDataChannelStats,
  type RTCIceCandidatePairStats,
  type RTCIceCandidateStats,
  type RTCIceLocalCandidateStats,
  type RTCIceLocalCandidateStatsMapped,
  type RTCIceRemoteCandidateStats,
  type RTCIceRemoteCandidateStatsMapped,
  type RTCInboundRtpAudioStreamStats,
  type RTCInboundRtpStreamStats,
  type RTCInboundRtpVideoStreamStats,
  type RTCMediaSourceStats,
  type RTCOutboundRtpAudioStreamStats,
  type RTCOutboundRtpStreamStats,
  type RTCOutboundRtpVideoStreamStats,
  type RTCPacketsStats,
  type RTCPeerConnectionStats,
  type RTCPublisherPeerConnectionStats,
  type RTCPublisherPeerConnectionStatsAudioTrackMapped,
  type RTCPublisherPeerConnectionStatsAudioTracksMapped,
  type RTCPublisherPeerConnectionStatsMapped,
  type RTCPublisherPeerConnectionStatsReading,
  type RTCPublisherPeerConnectionStatsTrackMapped,
  type RTCPublisherPeerConnectionStatsVideoTrackMapped,
  type RTCPublisherPeerConnectionStatsVideoTracksMapped,
  type RTCReceivedRtpStreamStats,
  type RTCRemoteInboundRtpAudioStreamStats,
  type RTCRemoteInboundRtpStreamStats,
  type RTCRemoteInboundRtpVideoStreamStats,
  type RTCRemoteOutboundRtpStreamStats,
  type RTCRtpStreamStats,
  type RTCSentRtpStreamStats,
  type RTCSubscriberPeerConnectionStats,
  type RTCSubscriberPeerConnectionStatsAudioTrackMapped,
  type RTCSubscriberPeerConnectionStatsAudioTracksMapped,
  type RTCSubscriberPeerConnectionStatsMapped,
  type RTCSubscriberPeerConnectionStatsReading,
  type RTCSubscriberPeerConnectionStatsTrackMapped,
  type RTCSubscriberPeerConnectionStatsVideoTrackMapped,
  type RTCSubscriberPeerConnectionStatsVideoTracksMapped,
  type RTCTransportStats,
  type RTCVideoSourceStats,
  type RTCVideoSourceStatsMapped,
  type RegisterId,
  RequiredDeviceIdError,
  type ResponseExtender,
  type ResultFailure,
  type ResultSuccess,
  type RoomCapacityExceededError,
  RoomConnectedError,
  type RoomNotFoundError,
  type RoomNotSupportedByClientError,
  SDK_VERSION,
  ScreenShareUserCanceledError,
  type SwitchingMode,
  type SyncResult,
  type TakeProperty,
  type Timestamp,
  USER_MEDIA_TYPE,
  type UnauthorizedError,
  type UnknownError,
  type Unsubscriber$1 as Unsubscriber,
  UserDeniedPermissionError,
  type UserMediaPermissionState,
  type UserMediaType,
  UserNameRequiredError,
  type VideoInputOptions,
  type WebRTCMetricsCollected,
  type WebRTCMetricsEvent,
  type WebRTCMetricsService,
  activityPlugin,
  createJazzClient,
  createJazzSdk,
  createJazzSdkWeb,
  createJazzWebSdk,
  createSdkToken,
  displayEndpointsPlugin,
  getActivity,
  getConnectionQualityService,
  getDisplayEndpoints,
  getJazzClient,
  getJazzSdk,
  getJoinWarmUp,
  getLobby,
  getLocalDevices,
  getMediaMetricsService,
  getPowerProfileService,
  handleEvent,
  handleEvents,
  handleQuery,
  handleQueryChanges,
  isExtender,
  lobbyPlugin,
  localDeviceManagerPlugin,
  mediaMetricsPlugin,
  watchAtom,
  withAnonymousCreateRoom,
  withAnonymousJoin,
};
