import EventEmitter from 'events';
import ExperienceSdkCore from './ExperienceSdkCore';
import NotificationHub from './NotificationHub';
import PerformanceMonitor from './PerformanceMonitor';
let experienceSdkCore = null;
/* eslint-enable max-len */
/**
 * Initializes ExperienceSdk
 * Important: Needs to be called before preLoad and start!
 * When done, emits EventTypes.initDone
 * If config.autoPreLoad is true, calls preLoad method
 * If config.autoStart is true, calls start method
 * @tutorial getting-started
 * @param {Object} config config for initialization.
 * @param {string} config.accountHash The account hash to identify clients' account.
 * @param {boolean} config.autoPreLoad The setting to define if related packages/assets will be preloaded with init
 * method or separately with calling preLoad() method.
 * @param {boolean} config.autoStart The setting to define if feature tracking will start automatically after sdk
 * initialized and media stream accessed.
 * @param {Array.<(Object|ClassifiersRawDataFeatureConfig)>}config.features Array of configurations for features
 * to calculate with experience SDK.
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function init(config = {}) {
    await experienceSdkCore.init(config);
}
/**
 * Starts the preloading of needed assets, codes, which may take longer.
 * Emits EventTypes.initDone if finished.
 * Important: init method needs to be called before!
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function preLoad() {
    await experienceSdkCore.preLoad();
}
/**
 * Starts prediction, if preLoad method haven't called yet, it will call it first.
 * Important: init method needs to be called before!
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function start() {
    await experienceSdkCore.start();
}
/**
 *Stops all the trackers and features. Releases the camera if not recieved through config.
 *
 * Cannot restart tracking if camera is released.
 * @param {bool} releaseCamera Force release camera stream. If the camera stream is released,
 * the sdk cannot be restarted!
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function stop(releaseCamera) {
    await experienceSdkCore.stop(releaseCamera);
}
/**
 * Calls the callback function with the occurred error object.
 * @param {*} callback Client's callback function
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function error(callback) {
    experienceSdkCore.error(callback);
}
/**
 * @callback eventCallback
 * @param  {Object} args - event's arguments
 * @memberOf ExperienceSdk
 */
/**
 * @param {string} eventName Client's callback function
 * @param {eventCallback} callback Client's callback function
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function on(...args) {
    experienceSdkCore.on(...args);
}
/**
 * Unsubscribe from an event by it's name and the listener
 * @param {string} eventName Name of the event to unsubscribe from
 * @param {object} listener Event listener which was subscribed on event
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function off(eventName, listener) {
    experienceSdkCore.removeListener(eventName, listener);
}
/**
 * Unsubscribe from an event for all the listener
 * @param {string} eventName Name of the event to unsubscribe from
 * @returns {Promise}
 * @memberOf ExperienceSdk
 */
async function offAll(eventName) {
    experienceSdkCore.removeAllListeners(eventName);
}
/**
 * Gets the ExperienceSDK's running state, which can be:
 * NotInitialized, Idle, Running, Error
 * @returns {string}
 * @memberOf ExperienceSdk
 */
function getRunningState() {
    return experienceSdkCore.runningState;
}
/**
 * Marks the start of a special interval.
 * @param {string} intervalType Custom string to identify the what the marked interval represents.
 * E.g. it can be "ad" or "content_video".
 * At most one interval of a given type can be open at any given point in time.
 * @param {string} contentId A domain specific custom identifier of the content of the marked interval.
 * @param {timestamp} intervalStart This parameter can be used for marking intervals
 * that actually started before the method call.
 * If you do not specify it, the ExperienceSDK will use the current time as the timestamp.
 * @param {int} timeoutSeconds Number of seconds after which the interval
 * will automatically be considered closed by the backend,
 * even if no ending signal is received.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function markIntervalStart(intervalType, contentId, intervalStart, timeoutSeconds) {
    experienceSdkCore.markIntervalStart(intervalType, contentId, intervalStart, timeoutSeconds);
}
/**
 * Marks the end of a started interval.
 * @param {string} intervalType Custom string to identify the what the marked interval represents.
 *  E.g. it can be "ad" or "content_video".
 *  At most one interval of a given type can be open at any given point in time.
 * @param {timestamp} intervalEnd This parameter can be used for marking intervals
 * that actually started before the method call.
 * If you do not specify it, the ExperienceSDK will use the current time as the timestamp.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function markIntervalEnd(intervalType, intervalEnd) {
    experienceSdkCore.markIntervalEnd(intervalType, intervalEnd);
}
/**
 * Sends a custom string meta-data property for the given interval.
 * @param {string} intervalType The interval type to which the property will be assigned.
 * @param {string} key The key of the property.
 * @param {string} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setIntervalInfoString(intervalType, key, value) {
    experienceSdkCore.setIntervalInfoString(intervalType, key, value, 'string');
}
/**
 * Sends a custom string meta-data property for the given interval.
 * @param {string} intervalType The interval type to which the property will be assigned.
 * @param {string} key The key of the property.
 * @param {bool} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setIntervalInfoBoolean(intervalType, key, value) {
    experienceSdkCore.setIntervalInfoBoolean(intervalType, key, value, 'boolean');
}
/**
 * Sends a custom string meta-data property for the given interval.
 * @param {string} intervalType The interval type to which the property will be assigned.
 * @param {string} key The key of the property.
 * @param {number} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setIntervalInfoNumber(intervalType, key, value) {
    experienceSdkCore.setIntervalInfoNumber(intervalType, key, value, 'number');
}
/**
 * Gets participantId
 * @returns {string}
 * @memberOf ExperienceSdk
 */
function getSourceId() {
    return experienceSdkCore.getSourceId();
}
/**
 * Deletes all data stored on the client side.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function deleteSourceData() {
    experienceSdkCore.deleteSourceData();
}
/**
 * Adds a custom string property to the custom property map of all subsequent events.
 * @param {string} key The key of the property.
 * @param {*} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function addCustomProperty(key, value) {
    experienceSdkCore.addCustomProperty(key, value);
}
/**
 * Return key-value pairs of custom properties.
 * @returns {object} Key-value pairs.
 * @memberOf ExperienceSdk
 */
function getCustomProperties() {
    return experienceSdkCore.getCustomProperties();
}
/**
 * Sends a custom string meta-data property for the source.
 * @param {string} key The key of the property.
 * @param {string} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setSourceAttributeString(key, value) {
    return experienceSdkCore.setSourceAttributeString(key, value);
}
/**
 * Sends a custom string meta-data property for the source.
 * @param {string} key The key of the property.
 * @param {number} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setSourceAttributeNumber(key, value) {
    return experienceSdkCore.setSourceAttributeNumber(key, value);
}
/**
 * Sends a custom string meta-data property for the source
 * @param {string} key The key of the property.
 * @param {bool} value The value of the property.
 * @returns {void}
 * @memberOf ExperienceSdk
 */
function setSourceAttributeBoolean(key, value) {
    return experienceSdkCore.setSourceAttributeBoolean(key, value);
}
export default class ExperienceSdk extends EventEmitter {
    /**
     * Creates an instance of ExperienceSdk.
     * @class
     * @name ExperienceSdk
     */
    constructor() {
        super();
        experienceSdkCore = new ExperienceSdkCore();
        this.init = init;
        this.preLoad = preLoad;
        this.start = start;
        this.stop = stop;
        this.error = error;
        this.on = on;
        this.off = off;
        this.offAll = offAll;
        this.getRunningState = getRunningState;
        this.getSourceId = getSourceId;
        this.performanceMonitor = PerformanceMonitor;
        this.version = experienceSdkCore.version;
        this.markIntervalStart = markIntervalStart;
        this.markIntervalEnd = markIntervalEnd;
        this.setIntervalInfoString = setIntervalInfoString;
        this.setIntervalInfoBoolean = setIntervalInfoBoolean;
        this.setIntervalInfoNumber = setIntervalInfoNumber;
        this.deleteSourceData = deleteSourceData;
        this.addCustomProperty = addCustomProperty;
        this.getCustomProperties = getCustomProperties;
        this.setSourceAttributeString = setSourceAttributeString;
        this.setSourceAttributeNumber = setSourceAttributeNumber;
        this.setSourceAttributeBoolean = setSourceAttributeBoolean;
        experienceSdkCore.eventsToPublish.forEach((eventName) => {
            NotificationHub.on(eventName, (data) => {
                this.emit(eventName, data);
            });
        });
        this.publishingEventNames = experienceSdkCore.eventsToPublish;
    }
}