import EventEmitterProto from 'eventemitter3';
import { WebapiResult, WebapiClientUtil } from '@telenia/webapiclient/client';
import { TLink, WebrtDeviceManager, WebrtcConfig, IceServer, TrickleIcePolicy, MediaConfiguration } from '@telenia/webapiclient/webrtc';

interface LogEntry {
    level: Log.LogLevel;
    time: Date;
    message: string;
}
declare class Log {
    /**
     * create instance of Log that log with pkg prefix
     */
    static of(pkg: string, client?: Client): Log;
    get config(): Log.Logger;
    log(): (level: Log.LogLevel, message: any, ...args: any) => void;
    get verbose(): (message: any, ...args: any) => void;
    get debug(): (message: any, ...args: any) => void;
    get info(): (message: any, ...args: any) => void;
    get warn(): (message: any, ...args: any) => void;
    get error(): (message: any, ...args: any) => void;
    get fatal(): (message: any, ...args: any) => void;
}
declare namespace Log {
    enum LogLevel {
        Verbose = 1,
        Debug = 2,
        Info = 3,
        Warn = 4,
        Error = 5,
        Fatal = 6,
        None = 7
    }
    interface LogStorageConfig {
        /**
         * store log entry
         */
        store?: (entry: LogEntry) => Promise<void>;
        /**
         * request stored log entry
         */
        dump?: () => Promise<Iterable<LogEntry>>;
    }
    interface LogConfig {
        /**
         * enable logging
         * @default true
         */
        enabled?: boolean;
        /**
         * log plain object as json object
         * @default false
         */
        objectToJson?: boolean;
        /**
         * minimun log level (included)
         * @default Level.debug
         */
        logLevel?: LogLevel;
        /**
         * log timestamp
         * @default true
         */
        timestamp?: boolean;
        /**
         * storage log configuration
         * if not set use IndexedDBLogStore (with 1hour retention)
         * @default undefined
         */
        storage?: LogStorageConfig;
    }
    abstract class Logger {
        /**
         * enabled to log identification of {@link Client} instance on every log line
         */
        abstract get instanceIdLogged(): boolean;
        /**
         * do JSON.stringify of logged args instead of direct print
         */
        abstract get objectToJson(): boolean;
        /**
         * get current log level
         */
        abstract get logLevel(): LogLevel;
        /**
         * prefix added to every log line
         */
        abstract get prefix(): string;
        /**
         * enabled to print timestamp on every log line
         */
        abstract get timestamp(): boolean;
    }
}

declare class EventEmitter<E extends EventTypes = string | symbol, Context extends any = any> extends EventEmitterProto<E, Context> {
}
declare type EventTypes = EventEmitterProto.ValidEventTypes;

declare class SearchResult<T> extends EventEmitter<SearchResultEventMap<T>> {
    /**
     * Fired when response return data
     * @event
     * @param data T data received
     * @param index number indexed data
     * @param tot total result to received
     *
     * ```javascript
     * result.on("data", function(data, index, tot) {
     *   console.log("received " + index + " of " + tot + " data", data);
     * });
     * ```
     */
    static data: string;
    /**
     * Fired when response return error
     * @event
     * @param error data received
     *
     * ```javascript
     * result.on("error", function(error) {
     *   console.log("error on receive result", error);
     * });
     * ```
     */
    static error: string;
    /**
     * Fired when response complete
     * @event
     * @param empty
     *
     * ```javascript
     * result.on("complete", function() {
     *   console.log("result complete");
     * });
     */
    static complete: string;
}
interface SearchResultEventMap<T> {
    data: (data: T, index: number, tot: number) => void;
    error: (error: any) => void;
    complete: () => void;
}

declare namespace CallHistory {
    class CallHistoryResult extends SearchResult<CallHistoryItem> {
        readonly options: CallHistoryRequest;
    }
    interface CallHistoryRequest {
        pageSize: number;
        pageNumber: number;
    }
    interface CallHistoryItem {
        /**
         * @return the devStatuses
         */
        devStatuses?: CallHistoryDevStatus[];
        /**
         * @return the dialStatuses
         */
        dialStatuses?: CallHistoryDialStatus[];
        /**
         * @return the transportType
         */
        transportType?: TransportType;
        /**
         * @return the type
         */
        type?: CallHistoryType;
    }
    /**
     * Values:
     * - `TRASF` - transfer
     * - `TRASF_CANCEL` - transfer and caller hangup
     * - `TRASF_ANSWER` - transfer with success
     * - `TRASF_VM` - transfer to voicemail and caller rec a message
     * - `TRASF_VM_NO` - transfer to voicemail and caller hangup without a message
     * - `RETURN` - call return to caller
     */
    enum CallHistoryDevStatus {
        /**
         * transfer
         */
        TRASF = "TRASF",
        /**
         * transfer and caller hangup
         */
        TRASF_CANCEL = "TRASF_CANCEL",
        /**
         * transfer with success
         */
        TRASF_ANSWER = "TRASF_ANSWER",
        /**
         * transfer to voicemail and caller rec a message
         */
        TRASF_VM = "TRASF_VM",
        /**
         * transfer to voicemail and caller hangup without a message
         */
        TRASF_VM_NO = "TRASF_VM_NO",
        /**
         * call return to caller
         */
        RETURN = "RETURN"
    }
    /**
     * call status
     *
     * Values:
     * - `CHANUNAVAIL` - Channel unavailable.
     * - `CONGESTION` - Congestion
     * - `NOANSWER` - No answer
     * - `BUSY` - Busy call
     * - `ANSWER` - Answered
     * - `CANCEL` - Call is cancelled by caller
     * - `ERROR` - generic error
     * - `NON_PRESENTE`
     * - `ALWAYS` - unconditionally foward
     * - `ENABLE_FROM_PHONE` - foward enable by phone
     * - `PICKUPED` - pickuped call
     * - `PICKUPER` - user pickup call
     * - `TVOX_NO_PERMISSION` - user can not call number
     * - `DONTCALL` - DND
     * - `REJECTED` - call rejected from called user
     */
    enum CallHistoryDialStatus {
        /**
         * Channel unavailable.
         */
        CHANUNAVAIL = "CHANUNAVAIL",
        /**
         * Congestion
         */
        CONGESTION = "CONGESTION",
        /**
         * No answer
         */
        NOANSWER = "NOANSWER",
        /**
         * Busy call
         */
        BUSY = "BUSY",
        /**
         * Answered
         */
        ANSWER = "ANSWER",
        /**
         * Call is cancelled by caller
         */
        CANCEL = "CANCEL",
        /**
         * generic error
         */
        ERROR = "ERROR",
        NON_PRESENTE = "NON_PRESENTE",
        /**
         * unconditionally foward
         */
        ALWAYS = "ALWAYS",
        /**
         * foward enable by phone
         */
        ENABLE_FROM_PHONE = "ENABLE_FROM_PHONE",
        /**
         * pickuped call
         */
        PICKUPED = "PICKUPED",
        /**
         * user pickup call
         */
        PICKUPER = "PICKUPER",
        /**
         * user can not call number
         */
        TVOX_NO_PERMISSION = "TVOX_NO_PERMISSION",
        /**
         * DND
         */
        DONTCALL = "DONTCALL",
        /**
         * call rejected from called user
         */
        REJECTED = "REJECTED"
    }
    enum TransportType {
        PHONE = "PHONE",
        VOICEMAIL = "VOICEMAIL",
        FAX = "FAX",
        SMS = "SMS"
    }
    enum CallHistoryType {
        INBOUND = "INBOUND",
        OUTBOUND = "OUTBOUND"
    }
}

declare class ProfileAgent extends Profile<ProfileAgent.EventMap> {
    /**
     * Fired after server notify call on queue
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("call_on_queue", function(totalCallOnQueue) {
     *   console.log("call on queue " + totalCallOnQueue);
     * });
     * ```
     */
    static call_on_queue: string;
    /**
     * Fired after server notify call on queue
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("progress", function(serviceCode, callOnQueue) {
     *   console.log("call on queue " + callOnQueue + " for service " + serviceCode);
     * });
     * ```
     */
    static service_call_on_queue: string;
    get status(): string;
    startNotifyServiceCallQueue(): Promise<void>;
    stopNotifyServiceCallQueue(): Promise<void>;
    setReady(): Promise<boolean>;
    setNotReady(): Promise<boolean>;
    getAllActivityCode(): Promise<WebapiResult.ActivityCode[]>;
    setActivityCode(action: WebapiResult.SetActivityCodeAction): Promise<boolean>;
    getCurrentSkillsetsWithProfiles(): Promise<any>;
}
declare namespace ProfileAgent {
    interface EventMap {
        call_on_queue: (callOnQueue: number) => void;
        service_call_on_queue: (serviceCode: string, callOnQueue: number) => void;
        status_changed: (state: string) => void;
    }
}
declare enum ProfileType {
    /**
     * unify communication common profile
     */
    UC = "UC",
    /**
     * contact center agent profile
     */
    AG = "AG",
    /**
     * external agent profile
     */
    AG_EXTERNAL = "AG_EXTERNAL",
    /**
     * remote agent profile
     */
    AG_REMOTE = "AG_REMOTE",
    /**
     * telenia queue manager profile
     */
    TQM = "TQM"
}
declare class Profile<E extends EventTypes = any> extends EventEmitter<E> {
    readonly id: number;
    readonly type: ProfileType;
    get label(): string;
    /**
     * return this is profile in use
     */
    get isInUse(): boolean;
    /**
     * return how a profile can record call
     */
    get callRecording(): Profile.CallRecording;
    useProfile(): Promise<void>;
}
declare namespace Profile {
    /**
     * how a profile can record call.
     */
    enum CallRecording {
        /**
         * no registration enabled
         */
        DISABLED = "DISABLED",
        /**
         * registration is available on demand
         */
        ON_DEMAND = "ON_DEMAND",
        /**
         * registration is available on demand with ability to adding note
         */
        ON_DEMAND_WITH_NOTE = "ON_DEMAND_WITH_NOTE",
        /**
         * registration is automatic enabled for every call
         */
        AUTOMATIC = "AUTOMATIC",
        /**
         * registration is automatic enabled for every call with ability to adding note
         */
        AUTOMATIC_WITH_NOTE = "AUTOMATIC_WITH_NOTE",
        /**
         * registration is available with service digits on telephone
         */
        ENABLED_ON_PHONE = "ENABLED_ON_PHONE"
    }
}

/**
 * A User represents place to manage user activity
 */
declare class User extends EventEmitter<User.EventMap> {
    /**
     * Fired after error on useDevice
     * @event
     * @param empty
     *
     * ```javascript
     * client.on("error_no_profile", function() {
     *   console.log("user logged use wrong profile");
     * });
     * ```
     */
    static error_no_profile: string;
    /**
     * Fired for error on profile available
     * @event
     * @param empty
     *
     * ```javascript
     * client.on("error_no_profile_available", function() {
     *   console.log("user logged has any available profile");
     * });
     * ```
     */
    static error_no_profile_available: string;
    /**
     * Fired after succesful useProfile
     * @event
     * @param profile {@link Profile} profile selected
     *
     * ```javascript
     * client.on("profile_selected", function(profile) {
     *   console.log("user logged select profile");
     * });
     * ```
     */
    static profile_selected: string;
    /**
     * Fired after TVox notify that one profile is removed
     * @event
     * @param profile {@link Profile} profile selected
     *
     * ```javascript
     * client.on("profile_removed", function(profile) {
     *   console.log("profile is removed from availableProfile");
     * });
     * ```
     */
    static profile_removed: string;
    /**
     * Fired after TVox notify that one profile is added
     * @event
     * @param profile {@link Profile} profile selected
     *
     * ```javascript
     * client.on("profile_added", function(profile) {
     *   console.log("new profile is added to availableProfile");
     * });
     * ```
     */
    static profile_added: string;
    /**
     * current state of this client instance
     */
    get state(): User.State;
    /**
     * current user info
     */
    readonly info: User.Data;
    /**
     * profile available to user, for select one use method useProfile
     */
    readonly availableProfile: Profile[];
    get statusMonitor(): UserStatusMonitor;
    /**
     * tell server what profile to use.
     * If param is null or undefined it select one from {@link User.availableProfile} by this logic:
     *
     * 1. availableProfile[0] if availableProfile.length = 1
     * 2. first {@link ProfileType.UC} profile
     * 3. first {@link ProfileType.AG} profile
     *
     * If passed profile is unavailable or any of previous step can select one it change {@link User.state} to {@link User.State.ERROR_NO_PROFILE}
     * If availableProfile.length = 0 it change {@link User.state} to {@link User.State.ERROR_NO_PROFILE_AVAILABLE}
     */
    useProfile(profile?: Profile): Promise<void>;
    /**
     * search addressbook contacts
     *
     * @param {Contact.SearchContactOptions} options
     * @returns {Promise<Contact.SearchContactResult>} a promise resolved when search is done
     *
     * ```javascript
     * client.user.searchContact({toSearch: "john woo", pageNumber: 1, pageSize: "20"})
     * .catch(function(error) {
     *      console.error("searchContact - ERROR", error);
     * })
     * .then(function(result) {
     *    result
     *        .on("data", function(data, index, total){
     *              console.log("searchContact - result - DATA", data);
     *          })
     *       .on("error", function(error) {
     *              console.error("searchContact - result - ERROR");
     *          })
     *       .on("complete", function() {
     *              console.log("searchContact - result - COMPLETE");
     *          });
     * });
     * ```
     *
     */
    searchContact(options: Contact.SearchContactOptions): Promise<Contact.SearchContactResult>;
    /**
     * run getContact
     * @param {string} id
     * @returns {(Promise<Contact | null>)} a promise resolved when getContact is done
     *
     * ```javascript
     * client.user.getContact("0009922b-f9b4-409c-bca4-e476e34b1553")
     * .catch(function(error) {
     *      console.error("getContact - error", error);
     * })
     * .then(function(result) {
     *      console.log("getContact - response", result);
     * });
     * ```
     *
     */
    getContact(id: string): Promise<Contact | null>;
    getUserContactStatus(username: string): Promise<WebapiResult.UserContact>;
    /**
     * get call history
     *
     * @param {CallHistory.CallHistoryRequest} options
     * @returns {Promise<CallHistory.CallHistoryResult>} a promise resolved when get call history is done
     *
     * ```javascript
     * client.user.getCallHistory({pageNumber: 1, pageSize: "20"})
     * .catch(function(error) {
     *      console.error("Error on searchContact", error);
     * })
     * .then(function(result) {
     *    result
     *        .on("data", function(data, index, total){
     *              console.log("searchContact - result - DATA", data);
     *          })
     *       .on("error", function(error) {
     *              console.error("searchContact - result - ERROR", error);
     *          })
     *       .on("complete", function() {
     *              console.log("searchContact - result - COMPLETE");
     *          });
     * });
     * ```
     *
     */
    getCallHistory(options: CallHistory.CallHistoryRequest): Promise<CallHistory.CallHistoryResult>;
}
declare namespace User {
    enum State {
        LOGGED = "LOGGED",
        NOTLOGGED = "NOTLOGGED",
        ERROR_NO_PROFILE_AVAILABLE = "ERROR_NO_PROFILE_AVAILABLE",
        ERROR_NO_PROFILE = "ERROR_NO_PROFILE"
    }
    interface Data {
        userId?: string;
        username?: string;
        name?: string;
        surname?: string;
        profile?: Profile;
    }
    interface EventMap {
        error_no_profile: () => void;
        error_no_profile_available: () => void;
        profile_selected: (profile: Profile) => void;
        profile_removed: (profile: Profile) => void;
        profile_added: (profile: Profile) => void;
    }
}
declare class UserStatusMonitor extends EventEmitter<UserStatusMonitor.EventMap> {
    /**
     * Fired after phone status has changed
     * @event
     * @param data {@link UserStatusMonitor.PhoneChannelStatus} user status data
     *
     * ```javascript
     * client.on("phone_status_changed", function(data) {
     *   console.log("phone status changed to" + data.status);
     * });
     * ```
     */
    static phone_status_changed: string;
    /**
     * Fired after presence status has changed
     * @event
     * @param data {@link UserStatusMonitor.PresenceStatus} user status data
     *
     * ```javascript
     * client.on("presence_status_changed", function(data) {
     *   console.log("presence status changed to" + data.status);
     * });
     * ```
     */
    static presence_status_changed: string;
    start(): Promise<void>;
    stop(): Promise<void>;
    get phoneChannelStatus(): UserStatusMonitor.PhoneChannelStatus | undefined;
    get presenceStatus(): UserStatusMonitor.PresenceStatus | undefined;
}
declare namespace UserStatusMonitor {
    enum PhoneStatusValue {
        /**
         * Booked for service call
         */
        BOOKED = "BOOKED",
        /**
         * Busy in call
         */
        BUSY = "BUSY",
        /**
         * Not logged
         */
        NOTLOGGED = "NOTLOGGED",
        /**
         * Not ready to receive service call
         */
        NR = "NR",
        /**
         * Not ready to receive service call due to busy in other call
         */
        NR_BUSY = "NR_BUSY",
        /**
         * Ready to receive service call
         */
        READY = "READY",
        /**
         * Not ready for some time after service call end
         */
        WNR = "WNR"
    }
    enum PresenceStatusValue {
        /**
         * Free to chat.
         */
        CHAT = "CHAT",
        /**
         * Available (the default).
         */
        AVAILABLE = "AVAILABLE",
        /**
         * Away.
         */
        AWAY = "AWAY",
        /**
         * Away for an extended period of time.
         */
        XA = "XA",
        /**
         * Please do not disturb
         */
        DND = "DND",
        /**
         * unavailable
         */
        UNAVAILABLE = "UNAVAILABLE"
    }
    class PhoneChannelStatus {
        readonly status: PhoneStatusValue;
        readonly started: Date;
        readonly dnCallIn?: string | undefined;
        readonly dnCallOut?: string | undefined;
        readonly activityCode?: string | undefined;
        readonly activityCodeLevel2?: string | undefined;
        get timeInStateMillis(): number;
    }
    class PresenceStatus {
        readonly status: PresenceStatusValue;
        readonly message?: string | undefined;
        readonly until?: Date | undefined;
        constructor(status: PresenceStatusValue, message?: string | undefined, until?: Date | undefined);
    }
    interface EventMap {
        phone_status_changed: (status: PhoneChannelStatus) => void;
        presence_status_changed: (status: PresenceStatus) => void;
    }
}

declare class InternalUserContact extends Contact {
    readonly data: Contact.UserContact;
    get statusMonitor(): UserStatusMonitor;
}
declare class InternalServiceContact extends Contact {
    readonly data: Contact.ServiceContact;
}
declare class InternalShortNumberContact extends Contact {
    readonly data: Contact.ShortNumberContact;
}
declare class ExternalItemContact extends Contact {
    readonly data: Contact.ExternalContact;
}
declare class ExternalOrganizationContact extends Contact {
    readonly data: Contact.ExternalOrganizationContact;
}
declare class PersonalContact extends Contact {
    readonly data: Contact.PersonalContact;
}
declare abstract class Contact {
    readonly type: Contact.Type;
    readonly subtype: Contact.InternalSubType | Contact.ExternalSubType | null;
    readonly id: string;
}
declare namespace Contact {
    /**
     * represent result of searchContact methods.
     *
     *
     */
    class SearchContactResult extends SearchResult<Contact> {
        readonly requestOptions: SearchContactOptions;
    }
    interface GetContactOptions {
    }
    interface SearchContactOptions {
        type?: Contact.Type;
        pageSize: number;
        pageNumber: number;
        toSearch: string;
        /**
         * set with method to use for search
         * @type {("startWith" | "contains")} default is "startWith"
         */
        searchMethods: "startWith" | "contains";
    }
    enum Type {
        INTERNAL = "INTERNAL",
        EXTERNAL = "EXTERNAL",
        PERSONAL = "PERSONAL"
    }
    enum InternalSubType {
        SERVICE = "SERVICE",
        USER = "USER",
        SHORT_NUMBER = "SHORT_NUMBER"
    }
    enum ExternalSubType {
        ORGANIZATION = "ORGANIZATION"
    }
    enum AddressBookContactAddressType {
        MAIN = "MAIN",
        OTHER = "OTHER"
    }
    interface AddressBookContactAddress {
        cap?: string;
        city?: string;
        country?: string;
        district?: string;
        street?: string;
        type?: AddressBookContactAddressType;
    }
    interface AddressBookCategory {
        value?: string;
    }
    enum AddressBookContactMailType {
        INTERNET_WORK = "INTERNET_WORK",
        INTERNET_HOME = "INTERNET_HOME"
    }
    interface AddressBookContactMail {
        /**
         * @return the type
         */
        type?: AddressBookContactMailType;
        /**
         * @return the value
         */
        value?: string;
    }
    enum AddressBookContactNumberType {
        FAX = "FAX",
        HOME = "HOME",
        CELL = "CELL",
        WORK = "WORK",
        CELL_WORK = "CELL_WORK",
        FAX_WORK = "FAX_WORK",
        FAX_HOME = "FAX_HOME",
        CELL_HOME = "CELL_HOME",
        MAIN = "MAIN",
        OTHER = "OTHER"
    }
    interface AddressBookContactNumber {
        /**
         * @return the type
         */
        type?: AddressBookContactNumberType;
        /**
         * @return the value
         */
        value?: string;
    }
    enum AddressBookContactWebType {
        WORK = "WORK",
        HOME = "HOME"
    }
    interface AddressBookContactWeb {
        /**
         * @return the type
         */
        type?: AddressBookContactWebType;
        /**
         * @return the value
         */
        value?: string;
    }
    interface AddressBookContact {
        /**
         * @return the addresses
         */
        addresses?: AddressBookContactAddress[];
        /**
         * @return the categories
         */
        categories?: AddressBookCategory[];
        /**
         * @return the department
         */
        department?: string;
        /**
         * @return the display
         */
        display?: string;
        /**
         * @return the emails
         */
        emails?: AddressBookContactMail[];
        /**
         * @return the note
         */
        note?: string;
        /**
         * @return the numbers
         */
        numbers?: AddressBookContactNumber[];
        /**
         * @return the site
         */
        site?: string;
        /**
         * @return the webLinks
         */
        webLinks?: AddressBookContactWeb[];
    }
    interface UserContact extends AddressBookContact {
        /**
         * @return the customFields
         */
        customFields?: {
            [index: string]: string;
        };
        /**
         * @return the name
         */
        name?: string;
        /**
         * @return the surname
         */
        surname?: string;
        /**
         * @return the username
         */
        username?: string;
    }
    interface ServiceContact extends AddressBookContact {
        /**
         * @return the code
         */
        code?: string;
    }
    interface ShortNumberContact extends AddressBookContact {
    }
    interface ExternalContact extends AddressBookContact {
        /**
         * @return the company
         */
        company?: string;
        /**
         * @return the customFields
         */
        customFields?: {
            [index: string]: string;
        };
        /**
         * customer's code
         * @return the customerCode
         */
        customerCode?: string;
        /**
         * @return the memberof
         */
        memberof?: string;
        /**
         * @return the name
         */
        name?: string;
        /**
         * @return the otherName
         */
        otherName?: string;
        /**
         * @return the role
         */
        role?: string;
        /**
         * @return the surname
         */
        surname?: string;
        /**
         * @return the vip
         */
        vip?: boolean;
    }
    interface ExternalOrganizationContact extends AddressBookContact {
        /**
         * @return the company
         */
        company?: string;
        /**
         * @return the customFields
         */
        customFields?: {
            [index: string]: string;
        };
        /**
         * @return the name
         */
        name?: string;
        /**
         * @return the otherName
         */
        otherName?: string;
        /**
         * @return the role
         */
        role?: string;
        /**
         * @return the surname
         */
        surname?: string;
        /**
         * @return the vip
         */
        vip?: boolean;
    }
    interface PersonalContact extends AddressBookContact {
        /**
         * @return the name
         */
        name?: string;
        /**
         * @return the otherName
         */
        otherName?: string;
        /**
         * @return the surname
         */
        surname?: string;
    }
}

declare namespace C {
    enum LineType {
        SIP = "SIP",
        WEBRTC = "WEBRTC"
    }
}

declare class DeviceWebrtcMedia extends EventEmitter<DeviceWebrtcMedia.EventMap> {
    /**
     * Fired after device is connected/disconnected from system
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("device_change", function(status: MediaDeviceStatus, devices: MediaDevice) {
     *   console.log("device change", status);
     *   console.log("system devices is", devices);
     * });
     * ```
     */
    static device_change: string;
    /**
     * Fired after automatically select device to use after device is connected/disconnected from system
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("use_device_when_device_change", function(deviceToUpdate, ejectedDevice) {
     *   console.log("used device is ejected", ejectedDevice);
     *   console.log("some used device switch to", deviceToUpdate);
     * });
     * ```
     */
    static use_device_when_device_change: string;
    /**
     * Fired after detected connect devices that is never been managed
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("unused_device_added", function(devices) {
     *   console.log("new devices is added to system", devices);
     * });
     * ```
     */
    static unused_device_added: string;
    static get deviceIdToIgnore(): string[];
    /**
     * audio input device to use
     * null or undefined means using default device
     */
    get audioInput(): TLink.AudioInput | null | undefined;
    /**
     * audio output device to use
     * null or undefined means using default device
     */
    get audioOutput(): TLink.AudioOutput | null | undefined;
    /**
     * video input device to use
     * null or undefined means using default device
     * false means never use video input
     */
    get videoInput(): TLink.AudioInput | null | undefined | false;
    /**
     * audio output device to use for signaling (eg. ring)
     * null or undefined means using default device
     */
    get audioSignalOutput(): TLink.AudioOutput | null | undefined;
    /**
     * use device for webrtc call
     * In call is in progress it switch his device
     *
     * @param audioInput
     * @param audioOutput
     * @param videoInput
     * @param audioSignalOutput
     * @returns
     */
    useDevice(audioInput: DeviceWebrtcMedia.AudioInput | null, audioOutput: DeviceWebrtcMedia.AudioOutput | null, videoInput: DeviceWebrtcMedia.VideoInput | null | false, audioSignalOutput: DeviceWebrtcMedia.AudioOutput | null, audioNotificationOutput: DeviceWebrtcMedia.AudioOutput | null): Promise<void>;
    /**
     * Get an enumeration of available device.
     * If startMedia is true it request permission to usage devices (default was audio and video if available)
     * to retrive description of every device, otherwise return only id
     *
     * @param startMedia
     * @param acquireAudio
     * @param acquireVideo
     */
    getMediaDevice(startMedia: boolean, acquireAudio?: boolean, acquireVideo?: boolean): Promise<DeviceWebrtcMedia.MediaDevice>;
    /**
     * Request permission of audio device, video device or both.
     * Return true if given, false or DOMException otherwise
     */
    checkDevicePermission(permission: {
        audio: boolean;
        video: boolean;
    }): Promise<{
        audio: boolean;
        video: boolean;
    }>;
    /**
     * testing devices
     * Remember to call stop when test end, otherwise devices is keep engaged
     *
     * ---- audioInput and videoInput -----
     * object: exact device
     * null: system default device
     * boolean: false disabled - true system default device
     *
     * ---- audioOutput -----
     * object: exact device
     * null: system default device
     */
    testMediaDevice(audioInput: DeviceWebrtcMedia.AudioInput | null | boolean, videoInput: DeviceWebrtcMedia.VideoInput | null | boolean, audioOutput: DeviceWebrtcMedia.AudioOutput | null, videoContainer: HTMLElement): Promise<DeviceWebrtcMedia.MediaDeviceTest>;
}
declare namespace DeviceWebrtcMedia {
    /**
     * Represent history of usage devices by type
     * Devices is order by lastUsedAt
     */
    interface UseDeviceHistory {
        audioInput?: UseDeviceStored<AudioInput>[];
        audioOutput?: UseDeviceStored<AudioOutput>[];
        audioSignalOutput?: UseDeviceStored<AudioOutput>[];
        videoInput?: UseDeviceStored<VideoInput>[];
    }
    /**
     * Used to attach usage info of device
     */
    interface UseDeviceStored<Info extends DeviceInfo> {
        /**
         * device is device used
         * object: exact device
         * null: system default device
         * boolean: false disabled - true system default device
         */
        readonly device?: Info | null | false;
        /**
         * last instant of device is set as used
         */
        readonly lastUsedAt: Date;
        /**
         * device is explicitly used by user request
         */
        readonly setByUser: boolean;
        /**
         * return true if device is null or undefined
         */
        isDeviceDefault(): boolean;
        /**
         * return true if device is false
         */
        isDeviceDisabled(): boolean;
    }
    interface DeviceInfo {
        /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaDeviceInfo/deviceId) */
        readonly deviceId: string;
        /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaDeviceInfo/groupId) */
        readonly groupId: string;
        /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaDeviceInfo/kind) */
        readonly kind: "audioinput" | "audiooutput" | "videoinput";
        /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/MediaDeviceInfo/label) */
        readonly label: string;
    }
    interface AudioInput extends DeviceInfo {
    }
    interface VideoInput extends DeviceInfo {
    }
    interface AudioOutput extends DeviceInfo {
    }
    interface MediaDeviceStatus {
        readonly added: MediaDevice;
        readonly deleted: MediaDevice;
        readonly none: MediaDevice;
    }
    interface MediaDevice {
        readonly audioInput: AudioInput[];
        readonly videoInput: VideoInput[];
        readonly audioOutput: AudioOutput[];
    }
    class MediaDeviceTest extends EventEmitter<{
        audio_level: (value: number) => void;
    }> {
        start(): Promise<void>;
        stop(): Promise<void>;
        changeAudioVideoInput(audioInput?: AudioInput | null | false, videoInput?: VideoInput | null | false): Promise<void>;
        changeAudioOutput(audioOutput?: AudioOutput | null): Promise<void>;
    }
    interface EventMap {
        device_change: (status: MediaDeviceStatus, devices: MediaDevice) => void;
        use_device_when_device_change: (deviceToUpdate: {
            audioInput?: UseDeviceStored<AudioInput>;
            audioOutput?: UseDeviceStored<AudioOutput>;
            audioSignalOutput?: UseDeviceStored<AudioOutput>;
            videoInput?: UseDeviceStored<VideoInput>;
        }, ejectedDevice: boolean) => void;
        unused_device_added: (device: {
            audioInput?: AudioInput[];
            audioOutput?: AudioOutput[];
            videoInput?: VideoInput[];
        }) => void;
    }
}

declare class DeviceWebrtc implements Device {
    readonly label: string;
    readonly exten: string;
    readonly type: C.LineType;
    readonly configuration: DeviceWebrtc.Configuration;
    readonly media: DeviceWebrtcMedia;
    /**
     * run dialAudio
     * @returns {Promise<void>} a promise resolved if call is placed
     */
    dialAudio(phoneNumber: string, param?: Device.DialParam): Promise<void>;
    /**
     * run dialVideo
     * @returns {Promise<void>} a promise resolved if call is placed
     */
    dialVideo(phoneNumber: string, param?: Device.DialParam, videoContainer?: HTMLElement): Promise<void>;
}
declare namespace DeviceWebrtc {
    class Configuration {
        constructor(device: DeviceWebrtc);
        get options(): Configuration.Options;
        get media(): WebrtDeviceManager;
    }
    namespace Configuration {
        class Options {
            constructor(config: WebrtcConfig);
            get iceServers(): IceServer[] | undefined;
            set iceServers(iceServers: IceServer[] | undefined);
            get trickleIcePolicy(): TrickleIcePolicy | undefined;
            set trickleIcePolicy(trickleIcePolicy: TrickleIcePolicy | undefined);
            get iceGatherPolicy(): TLink.Sdp.Candidate.Type[] | undefined;
            set iceGatherPolicy(iceGatherPolicy: TLink.Sdp.Candidate.Type[] | undefined);
            get immediateRingback(): boolean | undefined;
            set immediateRingback(immediateRingback: boolean | undefined);
            get connectionTimeout(): number | undefined;
            set connectionTimeout(connectionTimeout: number | undefined);
            get deadStreamTimeout(): number | undefined;
            set deadStreamTimeout(deadStreamTimeout: number | undefined);
            get mediaConfiguration(): MediaConfiguration | undefined;
        }
    }
}

declare class DeviceSip implements Device {
    readonly label: string;
    readonly exten: string;
    readonly type: C.LineType;
    /**
     * run dial
     * @returns {Promise<void>} a promise resolved if call is placed
     */
    dial(phoneNumber: string, dialParamValue?: Device.DialParam): Promise<void>;
}

declare type DeviceTypes = DeviceSip | DeviceWebrtc;
interface Device {
}
declare namespace Device {
    interface DialParam {
        accessCode?: string;
        privateCall?: boolean;
        serviceCode?: string;
        note1?: string;
        note2?: string;
        contact?: Contact;
    }
}

/**
 * Call represent manager for every call instance
 *
 * @template T is {@link DeviceSip} or {@link DeviceWebrtc}
 * @template E is interface of event emitted
 */
declare abstract class Call<T extends DeviceTypes, E extends EventTypes = any> extends EventEmitter<E> {
    readonly callId: string;
    readonly direction: Call.Direction;
    readonly lookup: Call.Lookup;
    readonly detail: Call.Detail;
    /**
     * manager for call recording
     */
    readonly recording: Call.Recording;
    /**
     * unique identifier of call inside TVox
     * for TVox version <= 22.1.0 is same as {@link callId}
     * @deprecated use {@link detail}.id
     */
    get id(): string;
    /**
     * call start
     * @deprecated use {@link detail}.startTime
     */
    get startTime(): Date;
    /**
     * call end time
     * @deprecated use {@link detail}.endTime
     */
    get endTime(): Date | undefined;
    /**
     * call duration when end
     * @deprecated use {@link detail}.duration
     */
    get duration(): number | undefined;
    /**
     * service assigned to call
     * @deprecated use {@link detail}.service
     */
    get service(): {
        code: string;
        description: string;
    } | undefined;
    /**
     * extra data used for customization
     * @deprecated use {@link detail}.callData
     */
    get callData(): string | undefined;
    get features(): Call.CallFeature[];
    get lastUpdateMessageDate(): Date | null;
    /**
     * utility function to check if call has feature
     */
    hasFeature(feature: Call.CallFeature): boolean;
    /**
     * set callData on server
     */
    setCallData(data: string): Promise<boolean>;
}
declare namespace Call {
    enum Direction {
        INBOUND = "inbound",
        OUTBOUND = "outbound"
    }
    enum CallFeature {
        ACCEPT = "ACCEPT",
        ANSWER = "ANSWER",
        CANCEL = "CANCEL",
        CONFERENCE = "CONFERENCE",
        DIAL = "DIAL",
        HOLD = "HOLD",
        UNHOLD = "UNHOLD",
        GENERATE_DTMF = "GENERATE_DTMF",
        MONITOR_START = "MONITOR_START",
        MONITOR_STOP = "MONITOR_STOP",
        SETCALLDATA = "SETCALLDATA",
        TRANSFER_BLIND = "TRANSFER_BLIND",
        TRANSFER_ATTENDED = "TRANSFER_ATTENDED",
        REJECT = "REJECT",
        DIAL_ATXFER = "DIAL_ATXFER",
        ATXFER_CANCEL = "ATXFER_CANCEL"
    }
    enum AutomaticCallRecordingType {
        DISABLED = "DISABLED",
        AUTOMATIC_BY_SERVICE = "AUTOMATIC_BY_SERVICE",
        AUTOMATIC_BY_USER = "AUTOMATIC_BY_USER"
    }
    interface LookupDisplay {
        company?: string;
        name?: string;
        number?: string;
    }
    interface LookupEventMap {
        update_contact: (contact: Contact | null, lookup: Lookup) => void;
        update_display: (display: LookupDisplay, lookup: Lookup) => void;
        end: () => void;
    }
    class Lookup extends EventEmitter<LookupEventMap> {
        /**
         * Fired when lookup update contact
         *
         * @event
         */
        static update_contact: string;
        /**
         * Fired when lookup update display data
         *
         * @event
         */
        static update_display: string;
        /**
         * Fired when lookup end
         *
         * @event
         */
        static end: string;
        _contact?: Contact;
        readonly display: LookupDisplay;
        get contact(): Contact | undefined;
        get status(): "end" | "progress";
        get result(): LookupResult | undefined;
    }
    enum LookupResult {
        /**
         * success - we found an unique result to identify contact on lookup
         */
        SUCCESS = "SUCCESS",
        /**
         * lookup result is multiple
         */
        MULTIPLE = "MULTIPLE",
        /**
         * error on lookup
         */
        ERROR = "ERROR",
        /**
         * no result on lookup
         */
        NONE = "NONE"
    }
    interface RecordingEventMap {
        automatic_type_change: (value: Call.AutomaticCallRecordingType) => void;
        on_demand_start: () => void;
        on_demand_stop: () => void;
        on_demand_error: () => void;
    }
    class Recording extends EventEmitter<RecordingEventMap> {
        /**
         * Fired when automatic recording type change
         *
         * @event
         */
        static automatic_type_change: string;
        /**
         * Fired when on demand recording start
         *
         * @event
         */
        static on_demand_start: string;
        /**
         * Fired when on demand recording stop
         *
         * @event
         */
        static on_demand_stop: string;
        /**
         * Fired when on demand recording error
         *
         * @event
         */
        static on_demand_error: string;
        /**
         * Get on demand recording enabled
         */
        get onDemandEnabled(): boolean;
        /**
         * Get automatic recording enabled
         */
        get automaticEnabled(): boolean;
        /**
         * Get automatic recording type
         */
        get automaticType(): AutomaticCallRecordingType;
        /**
         * get on demand recording started
         */
        onDemandRecordingStarted(): boolean;
        /**
         * Get add note enabled
         */
        get addNoteEnabled(): boolean;
        /**
         * add note to call recording
         */
        addNote(note: string, additionalData?: string): Promise<boolean>;
        /**
         * Start on demand recording
         */
        startRecord(): Promise<boolean>;
        /**
         * Stop on demand recording
         */
        stopRecord(): Promise<boolean>;
    }
    interface DetailEventMap {
        update_detail: () => void;
    }
    class Detail extends EventEmitter<DetailEventMap> {
        /**
         * Fired when receiving updated call detail
         *
         * @event
         */
        static update_detail: string;
        /**
         * Unparsed info
         */
        get rawInfo(): {
            [index: string]: string | null | undefined;
            cli?: string | null | undefined;
            dnis?: string | null | undefined;
            idlastcall?: string | null | undefined;
            servizio?: string | null | undefined;
            sito?: string | null | undefined;
            sito_distribuzione?: string | null | undefined;
            skillset?: string | null | undefined;
            tipochiamata?: string | null | undefined;
            ivr_label?: string | null | undefined;
            mc_id?: string | null | undefined;
            mc_session?: string | null | undefined;
            mc_description?: string | null | undefined;
            mc_text?: string | null | undefined;
            abandoned_call_id?: string | null | undefined;
            callback_call_id?: string | null | undefined;
            interview_service?: string | null | undefined;
            campagna?: string | null | undefined;
            lista?: string | null | undefined;
            popupinfo: string | null;
        } | undefined;
        /**
         * unique identifier of call inside TVox
         * for TVox version <= 22.1.0 is same as {@link Call.callId}
         */
        get id(): string;
        get startTime(): Date;
        get endTime(): Date | undefined;
        get duration(): number | undefined;
        get remoteNumber(): string | undefined;
        get service(): {
            code: string;
            description: string;
        } | undefined;
        get callData(): string | undefined;
        get popupInfo(): {
            [index: string]: string;
        } | undefined;
        get skillset(): string | null | undefined;
        get ivrLabel(): string | null | undefined;
        get outboundCampaignId(): string | null | undefined;
        get outboundListId(): string | null | undefined;
    }
}

declare class CallSipForTransfer extends EventEmitter<CallSipForTransfer.EventMap> {
    /**
     * Fired when the callSipForTransfer is ended
     * @event
     * @param empty
     *
     * ```javascript
     * callSipForTransfer.on("ended", function() {
     *   console.log("call for transfer is ended");
     * });
     * ```
     */
    static ended: string;
    isEnded(): boolean;
    /**
     * {@link CallSip} instance associated of this {@link CallSipForTransefer} instance
     */
    get callSip(): CallSip;
    transfer(): Promise<boolean>;
    terminate(): Promise<boolean>;
}
declare namespace CallSipForTransfer {
    interface EventMap {
        ended: (call: CallSipForTransfer) => void;
    }
}
declare class CallSip extends Call<DeviceSip, CallSip.EventMap> {
    /**
     * Fired after server confirm call
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("connecting", function() {
     *   console.log("call connecting");
     * });
     * ```
     */
    static connecting: string;
    /**
     * Fired after server update call data
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("progress", function() {
     *   console.log("call progress");
     * });
     * ```
     */
    static progress: string;
    /**
     * Fired when the call is accepted
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("accepted", function() {
     *   console.log("call accepted");
     * });
     * ```
     */
    static accepted: string;
    /**
     * Fired when the call is ended
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("ended", function() {
     *   console.log("call ended");
     * });
     * ```
     */
    static ended: string;
    /**
     * Fired when the call is requested to ended
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("ended_request", function() {
     *   console.log("call ended is requested");
     * });
     * ```
     */
    static ended_request: string;
    /**
     * Fired for DTMF
     * @event
     * @param dtmf string|number dtmf managed
     *
     * ```javascript
     * call.on("newDTMF", function(dtmf) {
     *   console.log("call newDTMF", dtmf);
     * });
     * ```
     */
    static newDTMF: string;
    /**
     * Fired when the user puts call on hold.
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("hold", function() {
     *   console.log("call hold");
     * });
     * ```
     */
    static hold: string;
    /**
     * Fired when the user resumes call from hold.
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("unhold", function() {
     *   console.log("call unhold");
     * });
     * ```
     */
    static unhold: string;
    /**
     * Fired when feature change
     * @event
     * @param features {@link Call.CallFeature[]} new features
     * @param previousFeatures {@link Call.CallFeature[]}  previousFeatures
     *
     * ```javascript
     * call.on("change_features", function(features, previousFeatures) {
     *   console.log("call change features", features, previousFeatures);
     * });
     * ```
     */
    static change_features: string;
    /**
     * Fired when dialForTransfer has done
     * @event
     * @param callForTransfer {@link CallSipForTransfer} callForTranseferInstance
     *
     * ```javascript
     * call.on("new_call_for_transfer", function(callForTransfer) {
     *   console.log("callForTransfer done");
     * });
     * ```
     */
    static new_call_for_transfer: string;
    readonly type: C.LineType;
    get callSipForTransferInstance(): CallSipForTransfer | undefined;
    /**
     * return true if the call is in progress state (not established and not ended).
     */
    isInProgress(): boolean;
    /**
     * return true if the call is established.
     */
    isEstablished(): boolean;
    /**
     * return true if the call is ended.
     */
    isEnded(): boolean;
    /**
     * return true if the call is on hold.
     */
    isOnHold(): boolean;
    /**
     * answer the incoming call. This method is available for incoming call only.
     */
    answer(): Promise<boolean>;
    /**
     * terminate current call
     */
    terminate(): Promise<boolean>;
    /**
     * send one or multiple DTMF tones
     */
    sendDTMF(tone: string | number): Promise<boolean>;
    /**
     * puts the call on hold
     */
    hold(): Promise<boolean>;
    /**
     * resumes the call from hold
     */
    unhold(): Promise<boolean>;
    /**
     * The purpose is for check if we can call method dialForTransfer {@link CallSip}
     */
    isDialForTransferEnabled(): boolean;
    /**
     * On {@link CallSip} generated by generic sip device we can execute dial in purpose of future attendant transfer
     */
    dialForTransfer(phoneNumber: string, param?: Device.DialParam): Promise<CallSipForTransfer>;
    /**
     * transfer call to phone number, this is like blind transfer.
     * Calling the desired number on behalf of the caller, the original call then drops-off without waiting for the called number to be picked up
     */
    transferToNumber(number: string): Promise<boolean>;
    /**
     * transfer call to other sip call, this is like attended tranfer
     */
    transferToCall(call: CallSip): Promise<boolean>;
}
declare namespace CallSip {
    interface EventMap {
        hold: () => void;
        unhold: () => void;
        newDTMF: (tone: string | number) => void;
        ended: () => void;
        ended_request: () => void;
        accepted: () => void;
        progress: () => void;
        connecting: () => void;
        change_features: (features: Call.CallFeature[], previousFeatures: Call.CallFeature[]) => void;
        new_call_for_transfer: (call: CallSipForTransfer) => void;
    }
}

declare class CallWebrtc extends Call<DeviceWebrtc, CallWebrtc.EventMap> {
    /**
     * Fired after server confirm call
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("connecting", function() {
     *   console.log("call connecting");
     * });
     * ```
     */
    static connecting: string;
    /**
     * Fired after server update call data
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("progress", function() {
     *   console.log("call progress");
     * });
     * ```
     */
    static progress: string;
    /**
     * Fired when the call is accepted
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("accepted", function() {
     *   console.log("call accepted");
     * });
     * ```
     */
    static accepted: string;
    /**
     * Fired when the call is ended
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("ended", function() {
     *   console.log("call ended");
     * });
     * ```
     */
    static ended: string;
    /**
     * Fired when the call is requested to ended
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("ended_request", function() {
     *   console.log("call ended is requested");
     * });
     * ```
     */
    static ended_request: string;
    /**
     * Fired for DTMF
     * @event
     * @param dtmf string|number dtmf managed
     *
     * ```javascript
     * call.on("newDTMF", function(dtmf) {
     *   console.log("call newDTMF", dtmf);
     * });
     * ```
     */
    static newDTMF: string;
    /**
     * Fired when the user puts call on hold.
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("hold", function() {
     *   console.log("call hold");
     * });
     * ```
     */
    static hold: string;
    /**
     * Fired when the user resumes call from hold.
     * @event
     * @param empty
     *
     * ```javascript
     * call.on("unhold", function() {
     *   console.log("call unhold");
     * });
     * ```
     */
    static unhold: string;
    readonly type: C.LineType;
    get connectionManager(): CallWebrtc.ConnectionManager;
    /**
     * return true if the call is in progress state (not established and not ended).
     */
    isInProgress(): boolean;
    /**
     * return true if the call is established.
     */
    isEstablished(): boolean;
    /**
     * return true if the call is ended.
     */
    isEnded(): boolean;
    /**
     * return true if the call is on hold.
     */
    isOnHold(): boolean;
    /**
     * answer the incoming call. This method is available for incoming call only.
     */
    answerAudio(customFields?: Map<string, string>): Promise<boolean>;
    /**
     * answer the incoming call. This method is available for incoming call only.
     */
    answerVideo(customFields?: Map<string, string>, videoContainer?: HTMLElement): Promise<boolean>;
    /**
     * terminate the current call
     */
    terminate(): Promise<boolean>;
    /**
     * send one or multiple DTMF tones
     */
    sendDTMF(tone: string | number, playTone?: boolean): Promise<boolean>;
    /**
     * puts the call on hold
     */
    hold(): Promise<boolean>;
    /**
     * resumes the call from hold
     */
    unhold(): Promise<boolean>;
    /**
     * transfer call to phone number.
     * Calling the desired number on behalf of the caller, the original call then drops-off without waiting for the called number to be picked up
     */
    transferToNunber(number: string, accessCode?: string, data?: string[]): Promise<boolean>;
    /**
     * transfer call to other call
     */
    transferToCall(target: Call<DeviceTypes>): Promise<boolean>;
    /**
     * Mutes the local audio and/or video.
     */
    mute(options: CallWebrtc.MuteOptions): Promise<boolean>;
    /**
     * Unmutes the local audio and/or video.
     */
    unmute(options: CallWebrtc.MuteOptions): Promise<boolean>;
}
declare namespace CallWebrtc {
    class ConnectionManager extends EventEmitter<{
        connection_error: (error: any) => void;
        state: (state: ConnectionManager.State) => void;
        local_audio_level: (level: number) => void;
        remote_audio_level: (level: number) => void;
        stats: (stats: TLink.StatsEvent) => void;
    }> {
        startLocalAudioLevel(): void;
        stopLocalAudioLevel(): void;
        startRemoteAudioLevel(): void;
        stopRemoteAudioLevel(): void;
        startConnectionStats(): void;
        stopConnectionStats(): void;
    }
    namespace ConnectionManager {
        enum State {
            New = "new",
            Initializing = "initializing",
            Connecting = "connecting",
            Connected = "connected",
            Failing = "failing",
            Failed = "failed",
            Closing = "closing",
            Closed = "closed"
        }
    }
    interface MuteOptions {
        audio?: boolean;
        video?: boolean;
    }
    interface EventMap {
        hold: () => void;
        unhold: () => void;
        newDTMF: (tone: string | number) => void;
        ended_request: () => void;
        ended: () => void;
        accepted: () => void;
        progress: () => void;
        connecting: () => void;
        change_features: (features: Call.CallFeature[], previousFeatures: Call.CallFeature[]) => void;
    }
}

/**
 * A Phone represents place to manage phone activity
 */
declare class Phone extends EventEmitter<Phone.EventMap> {
    /**
     * Fired when new call is incoming or outgoing
     *
     * @event
     * @param call {@link CallSip} or {@link CallWebrtc} call to manage
     *
     * ```javascript
     * client.phone.on("newcall", function(call, detail) {
     *   console.log("new call is placed", call, detail);
     * });
     * ```
     */
    static newcall: string;
    /**
     * Fired when TVox Client state change
     *
     * @event
     * @param state {@link Phone.TVoxClientState}
     * @param detail {@link Phone.TVoxClientDetail}
     *
     * ```javascript
     * client.phone.on("tvoxclient_state_change", function(state, detail) {
     *   console.log("TVox Client state change", state, detail);
     * });
     * ```
     */
    static tvoxclient_state_change: string;
    /**
     * Fired when device to use is changed
     *
     * @event
     * @param newDevice {@link DeviceSip} or {@link DeviceWebrtc}
     * @param oldDevice {@link DeviceSip} or {@link DeviceWebrtc}
     *
     * ```javascript
     * client.phone.on("device_change", function(newDevice, oldDevice) {
     *   console.log("device change", oldDevice, newDevice);
     * });
     * ```
     */
    static device_change: string;
    /**
     * phone managed by TVox Client
     */
    get managedByTVoxClient(): boolean;
    set managedByTVoxClient(managedByTVoxClient: boolean);
    get state(): Phone.Status;
    get tvoxClientState(): Phone.TVoxClientState;
    get tvoxClientStateDetail(): Phone.TVoxClientDetail;
    readonly availableDevice: (DeviceSip | DeviceWebrtc)[];
    get device(): DeviceSip | DeviceWebrtc | null;
    handleChannelNotification(channelEvent: WebapiClientUtil.ChannelEvent): Promise<void>;
    /**
     * run useDevice to set current device to use
     * this method must be called after client initialization
     *
     * @param device must be one device taken by availableDevice
     * @returns a promise resolved true if device is ready to use
     */
    useDevice(device: DeviceSip | DeviceWebrtc): Promise<boolean>;
    /**
     * get calll instance by callid
     *
     * @param id call id to retrive
     * @returns null if callid is not available
     */
    getCall(id: string): CallSip | CallWebrtc | null;
}
declare namespace Phone {
    enum Status {
        READY = "READY",
        ERROR_NO_DEVICE_AVAILABLE = "ERROR_NO_DEVICE_AVAILABLE",
        ERROR_NO_DEVICE = "ERROR_NO_DEVICE"
    }
    enum TVoxClientState {
        UNKNOWN = "UNKNOWN",
        ACTIVE = "ACTIVE",
        INACTIVE = "INACTIVE",
        ACTIVATING = "ACTIVATING",
        DISCONNETING = "DISCONNETING"
    }
    enum TVoxClientPlatform {
        BROWSER = "BROWSER",
        APPLICATION = "APPLICATION"
    }
    interface TVoxClientDetail {
        lastUpdate: Date;
        platform?: Phone.TVoxClientPlatform;
        userAgent?: string;
    }
    interface EventMap {
        newcall: (call: CallSip | CallWebrtc, detail: {
            previousConnected: boolean;
        }) => void;
        tvoxclient_state_change: (state: TVoxClientState, detail: TVoxClientDetail) => void;
        device_change: (newDevice: DeviceSip | DeviceWebrtc | null, oldDevice: DeviceSip | DeviceWebrtc | null) => void;
    }
}

/**
 * A Transport represents place to manage communication to TVox
 */
declare class Transport extends EventEmitter<Transport.EventMap> {
    /**
     * Fired for each transport connection.
     * @event
     * @param empty
     *
     * ```javascript
     * client.transport.on("connect", function(user) {
     *   console.log("transport connected");
     * });
     * ```
     */
    static connect: string;
    /**
     * Fired for each transport disconnect.
     * @event
     * @param empty
     *
     * ```javascript
     * client.transport.on("disconnect", function(user) {
     *   console.log("transport disconnected");
     * });
     * ```
     */
    static disconnect: string;
    get state(): Transport.Status;
    /**
     * run connect
     * @returns {Promise<void>} a promise resolved when connect is done
     */
    connect(): void;
    /**
     * run disconnect
     * @returns {Promise<void>} a promise resolved when disconnect is done
     */
    disconnect(): void;
    /**
     * @returns {boolean} true if transport is connected
     */
    isConnected(): boolean;
}
declare namespace Transport {
    enum Status {
        CONNECTED = "CONNECTED",
        DISCONNECTED = "DISCONNECTED"
    }
    interface EventMap {
        connect: () => void;
        disconnect: () => void;
    }
}

/**
 * Action represents place to interact with server
 */
declare class Action {
    /**
     * upload file
     */
    uploadFile(file: File, options?: FileUploader.Options): FileUploader;
    /**
     * send feedback
     */
    sendFeedback(message?: string, attachments?: File[], options?: {
        compress?: {
            level: number;
            callbacks?: {
                onProgress?: (percent: number) => void;
            };
        };
        upload?: FileUploader.Options;
    }): Promise<boolean>;
    /**
     * generate feedback data
     */
    generateFeedbackData(message?: string, attachments?: File[]): Promise<Feedback.Data>;
}
/**
 * Manage single file upload/delete action
 */
interface FileUploader {
    get options(): FileUploader.Options;
    upload(): Promise<void>;
    delete(): Promise<void>;
}
declare namespace FileUploader {
    interface ChunkData {
        /**
         * the 0-based index of the associated partition
         */
        partIndex: number;
        /**
         * the byte offset of the current chunk
         */
        startByte: number;
        /**
         * the last byte of the current chunk
         */
        endByte: number;
        /**
         * the total number of partitions associated with the `File` or `Blob`
         */
        totalParts: number;
    }
    interface Options {
        chunking?: {
            /**
             * The maximum size of each chunk, in bytes
             *
             * @default `2000000`
             */
            partSize?: number;
        };
        callbacks?: {
            /**
             * Called during the upload, as it progresses, but only for the AJAX uploader.
             *
             * For chunked uploads, this will be called for each chunk.
             * Useful for implementing a progress bar
             *
             * @param number uploadedBytes : The number of bytes that have been uploaded so far
             * @param number totalBytes : The total number of bytes that comprise this file
             */
            onProgress?: (uploadedBytes: number, totalBytes: number) => void;
            /**
             * Called just before a chunk request is sent.
             *
             * @param ChunkData chunkData : An object encapsulating the current chunk of data about to be uploaded
             */
            onUploadChunk?: (chunkData: ChunkData) => void | Promise<any>;
            /**
             * This is similar to the `complete` event, except it is invoked after each chunk has been successfully uploaded.
             *
             * See the `uploadChunk` event for more information on the `chunkData` object
             *
             * @param ChunkData chunkData : An object encapsulating the current chunk of data about to be uploaded
             * @param Response response : The raw response from the server
             */
            onUploadChunkSuccess?: (chunkData: ChunkData, response: XMLHttpRequest) => void;
        };
    }
}
declare namespace Feedback {
    interface GenerateOptions {
        compress?: CompressOptions;
        upload?: FileUploader.Options;
    }
    interface CompressOptions {
        /**
         * compression level between 1 (best speed) and 9 (best compression), 0 for no compression
         */
        level: number;
        callbacks?: {
            /**
             * optional function called on each internal update with percent
             */
            onProgress?: (percent: number) => void;
        };
    }
    class Data {
        time: Date;
        name: string;
        /** populated by generateData */
        body: string;
        /** populated by generateData */
        logFile: Blob;
        /** populated by generateData */
        attachments: File[];
        toZipFile(options?: Feedback.CompressOptions): Promise<File>;
    }
}

/**
 * Client class represents a client access to TVox.
 */
declare class Client extends EventEmitter<Client.EventMap> {
    /**
     * Fired after login ad user initalization is done
     * @event
     */
    static ready: string;
    /**
     * Fired for a successfull login.
     * @event
     * @param user {@link User} user is same as client.user
     * @param loginData {@link LoginData} loginData is same as client.loginData
     *
     * ```javascript
     * client.on("logged_in", function(user, loginData) {
     *   console.log("user is logged in");
     * });
     * ```
     */
    static logged_in: string;
    /**
     * Fired for a successfull logout.
     * @event
     * @param user {@link User} user is same as client.user
     *
     * ```javascript
     * client.on("logged_out", function(user) {
     *   console.log("user is logged out");
     * });
     * ```
     */
    static logged_out: string;
    /**
     * Fired after a login il called
     * @event
     * @param user {@link User} user is same as client.user
     * @param credential {@link BasicCredential} or {@link BerearCredential} or {@link ExternalSessionIdCredential} credential used
     *
     * ```javascript
     * client.on("login_in_progress", function(user, credential) {
     *   console.log("user is trying to login", credential);
     * });
     * ```
     */
    static login_in_progress: string;
    /**
     * Fired after a login is failed
     * @event
     * @param error {@link LoginError}
     * @param user {@link User} user is same as client.user
     *
     * code attribute value of error can be
     *
     * * 401 Wrong credential
     * * 403 Password expired
     * * 497 User not enable to login from internet
     * * 498 User not enable to use TVox Client
     *
     * any value greater or equal to 500 is consider internal server error and must be notified to Telenia Customer Service
     *
     * ```javascript
     * client.on("login_failed", function(error, user) {
     *   console.log("user login failed", error);
     * });
     * ```
     */
    static login_failed: string;
    /**
     * current state of this client instance
     */
    get state(): Client.ClientState;
    /**
     * parameter used to instantiate client
     */
    readonly configuration: Client.ClientParameter;
    /**
     * place for interact with server (eg. upload file, send feedback)
     */
    readonly action: Action;
    /**
     * transport messages with TVox
     */
    readonly transport: Transport;
    /**
     * manage user data
     */
    readonly user: User;
    /**
     * manage phone
     */
    readonly phone: Phone;
    /**
     * client log configurator
     */
    get logConfigurator(): Client.ClientLogger;
    /**
     * identification of {@link Client} instance
     */
    get instanceId(): string;
    /**
     * login data
     */
    get loginData(): Client.LoginData | undefined;
    /**
     * Creates an instance of Client
     */
    constructor(configuration: Client.ClientParameter);
    /**
     * login with {@link Client.BasicCredential} or {@link Client.BerearCredential} or {@link Client.JWTCredential} or {@link Client.ExternalSessionIdCredential}
     *
     * ```javascript
     * // login with BasicCredential
     * client.login({username: "foo", password: "bar"}).then(() => {
     *           console.log("login ok");
     *       }, (err) => {
     *           console.error("login failed", err);
     *       });
     *
     * // login with BerearCredential
     * client.login({token: "aabbcc"}).then(() => {
     *           console.log("login ok");
     *       }, (err) => {
     *           console.error("login failed", err);
     *       });
     *
     * // login with JWTCredential
     * client.login({jwt: "xxxxx.yyyyy.zzzzz"}).then(() => {
     *           console.log("login ok");
     *       }, (err) => {
     *           console.error("login failed", err);
     *       });
     *
     * // login with ExternalSessionIdCredential
     * client.login({externalSessionId: "aabbcc"}).then(() => {
     *           console.log("login ok");
     *       }, (err) => {
     *           console.error("login failed", err);
     *       });
     * ```
     */
    login(credential: Client.Credential): Promise<void>;
    /**
     * run logout
     *
     * @param reason set reason for logout, example "end of shift"
     * @param note optional additional note of logout
     * @returns {Promise<void>} a promise resolved when the logout is done
     */
    logout(reason?: string, note?: string): Promise<boolean>;
    /**
     * check if this instance is logged
     *
     * @returns {boolean} true if this client is logged
     */
    isLogged(): boolean;
}
declare namespace Client {
    enum ClientState {
        /**
         * ready to use
         */
        READY = "READY",
        /**
         * login is required
         */
        LOGIN_REQUIRED = "LOGIN_REQUIRED",
        /**
         * login is in progress
         */
        LOGIN_IN_PROGRESS = "LOGIN_IN_PROGRESS",
        /**
         * login is requested and is failed
         */
        LOGIN_FAILED = "LOGIN_FAILED"
    }
    interface ClientParameter {
        /**
         * Url of WebApi Server
         * @required
         */
        url: string;
        /**
         * Set phone is managed by TVox Client
         * @default false
         */
        phoneManagedByTVoxClient: boolean;
        /**
         * log configuration
         */
        log?: Log.LogConfig;
        /**
         * Reconnecting configuration
         */
        retryOptions?: RetryOptions;
        /**
         * Webrtc parameter
         */
        webrtc?: ClientWebrtcParameter;
    }
    interface ClientWebrtcParameter {
        /**
         * custom useDevice history store
         */
        useDeviceHistoryStore?: {
            get: () => Promise<DeviceWebrtcMedia.UseDeviceHistory>;
            set: (history: DeviceWebrtcMedia.UseDeviceHistory) => Promise<DeviceWebrtcMedia.UseDeviceHistory>;
        };
    }
    /**
     * Type of allowed credential
     */
    type Credential = BasicCredential | BerearCredential | ExternalSessionIdCredential | JWTCredential;
    /**
     * Standard authentication (also called token authentication)
     */
    interface BasicCredential {
        username: string;
        password: string;
    }
    /**
     * Bearer authentication (also called token authentication) involves security tokens called bearer tokens that must be valid for TVox
     */
    interface BerearCredential {
        token: string;
    }
    /**
     * Authentication that involve sessionId or custom data validated outside of TVox
     */
    interface ExternalSessionIdCredential {
        externalSessionId: string;
    }
    /**
     * Authentication through jwt.
     *
     * JWT (json web token) represents a standard for exchanging claims securely between two parties.
     *
     * To use this credential, we need to generate a public and private key pair.
     * - Private key is used to sign JWT token and must be placed in a safe environment.
     * - Public key is used to verify JWT token and must be uploaded to TVox through OCC, from the section "External IDMs"
     *
     * Note: When creating a new external IDM on TVox, "code" and "alias" values are required, and they must be used in the JWT payload as explained below.
     *
     * JWT string is composed of three parts coded in Base64-URL strings: the header, the payload, and the signature separated by dots (.) ( see https://jwt.io )
     *
     * - Header
     * is a JSON object that must contains "alg", and "typ" keys.
     *  - alg: algorithm used to sign (typically "HS256" or "RSA"),
     *  - typ: type of token (value must be "JWT")
     *
     * - Payload
     * is a JSON object that contains a set of name/value pairs that describe the identity of the user that wants to sign in.
     * TVox needs the payload contains at least "sub", "aud" and "iss" claims.
     *  - sub: username of the user that wants to sign in
     *  - iss: code of external IDM created on TVox (must end with "__r_dm" suffix)
     *  - aud: alias of external IDM created on TVox
     *
     * - Signature
     * is a cryptographic signature of the header and payload. It must be generated with the private key previously maked.
     */
    interface JWTCredential {
        jwt: string;
    }
    class LoginData {
        /**
         * credential used on login
         */
        readonly credential: Credential;
        /**
         * access token assigned to current login
         */
        readonly accessToken: string;
        /**
         * server version where logged in
         */
        readonly serverVersion: string;
        /**
         * api version where logged in
         */
        readonly apiVersion: string;
        /**
         * session id of current login
         */
        readonly sessionId: string;
    }
    interface EventMap {
        ready: () => void;
        logged_in: (user: User, loginData: LoginData) => void;
        logged_out: (user: User) => void;
        login_in_progress: (user: User, credential: Credential) => void;
        login_failed: (error: LoginError, user: User) => void;
    }
    /**
     * Structure for error received by login method or login_failed event
     */
    interface LoginError {
        code: number;
        exceptionName: string;
        message: string;
    }
    class ClientLogger extends Log.Logger {
        get enabled(): boolean;
        set enabled(enabled: boolean);
        get objectToJson(): boolean;
        set objectToJson(objectToJson: boolean);
        set instanceIdLogged(instanceIdLogged: boolean);
        get instanceIdLogged(): boolean;
        set logLevel(logLevel: Log.LogLevel);
        get logLevel(): Log.LogLevel;
        get prefix(): string;
        set prefix(prefix: string);
        get timestamp(): boolean;
        set timestamp(timestamp: boolean);
    }
    interface RetryOptions {
        /**
         * The maximum amount of times to retry the operation.
         * If forever is true, retry will repeatedly use the timeouts array. Once all of its timeouts have been used up, it restarts with the first timeout, then uses the second and so on.
         * The formula used to calculate the individual timeouts is: Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout)
         * @default 10
         */
        retries?: number;
        /**
         * The exponential factor to use.
         * @default 1.2
         */
        factor?: number;
        /**
         * The number of milliseconds before starting the first retry.
         * @default 5000
         */
        minTimeout?: number;
        /**
         * The maximum number of milliseconds between two retries.
         * @default 30000
         */
        maxTimeout?: number;
        /**
         * Randomizes the timeouts by multiplying a factor between 1-2.
         * @default true
         */
        randomize?: boolean;
        /**
         * Never stop retry
         * @default true
         */
        forever?: boolean;
    }
}

declare const SDK_VERSION: string;
declare const LIB_VERSION: string;

export { Action, C, Call, CallHistory, CallSip, CallSipForTransfer, CallWebrtc, Client, Contact, Device, DeviceSip, type DeviceTypes, DeviceWebrtc, DeviceWebrtcMedia, EventEmitter, type EventTypes, ExternalItemContact, ExternalOrganizationContact, Feedback, FileUploader, InternalServiceContact, InternalShortNumberContact, InternalUserContact, LIB_VERSION, Log, type LogEntry, PersonalContact, Phone, Profile, ProfileAgent, ProfileType, SDK_VERSION, SearchResult, Transport, User, UserStatusMonitor };
