import ViewarApi from "@viewar/api";
import { Observable } from "rxjs";

declare module "@viewar/call" {

  interface JSONType {
    [key: string]: string | number | boolean | JSONType | JSONType[]
  }

  interface CallClientArgs {
    host?: string,
    debug?: boolean
  }

  interface JoinArgs {
    sessionId: string,
    username?: string,
    password?: string,
    userData: ClientData
  }

  enum ClientChange {
    JOIN = 'joined',
    LEFT = 'left',
    UPDATED = 'updated'
  }

  interface CallArgs {
    id: string,
    role: "receiver" | "sender"
  }

  interface AnswerCallArgs {
    syncScene?: boolean,
    data?: ClientData,
  }


  enum UserRole {
    Client = "Client",
    Admin = "Admin",
  }

  interface ClientData extends JSONType {
    available: boolean,
    timestamp: number,
  }

  interface Client {
    id: string,
    data: ClientData,
    role: UserRole,
  }

  interface CallClient {
    connect: () => boolean,
    join: (args: JoinArgs) => Promise<void>,
    leave: () => Promise<boolean>,
    setData: (data: ClientData) => void,
    call: (args: CallArgs) => Promise<boolean>,
    endCall: () => Promise<boolean>,
    answerCall: (args: AnswerCallArgs) => Promise<boolean>,
    rejectCall: () => Promise<boolean>,
    sendData: (type: string, data: JSONType) => Promise<boolean>,
    getData: <T>(type: string) => Observable<T>,
    reconnect: (attempt: number) => Promise<void>,
    readonly connected: boolean,
    readonly id: string,
    readonly session: string,
    readonly callActive: boolean,
    readonly incomingCall: Observable<{ id: string, userData: ClientData}>,
    readonly acceptedCall: Observable<{ id: string, data: JSONType}>,
    readonly refusedCall: Observable<void>,
    readonly endedCall: Observable<void>,
    readonly lineBusy: Observable<void>,
    readonly disconnect: Observable<void>,
    readonly clientsUpdate: Observable<{
      clients: Client[],
      id: string,
      type: ClientChange
    }>,
    readonly error: Observable<{ message: string }>,
    readonly isSupportAgent: boolean,
    readonly isUser: boolean,
    readonly clients: Client[],
  }

  function createCallClient(viewarApi: typeof ViewarApi, args: CallClientArgs): CallClient;
}