"use strict";
import {Logger} from "../common/Logger";
import {
    isDefinedAndNotEmpty,
    isNotDefined,
    isNotDefinedOrEmpty,
    toBoolean,
    updateObjectPropertiesFromAnOtherObject
} from "../common/Utils";

export {};

//const config = require("./config");
import {config, DataStoreType} from "./config";
import {isDefined, loadConfigFromIniFile, saveConfigFromIniFile} from "../common/Utils.js";
import {XMPPUTils} from "../common/XMPPUtils";

const xmppUtils = XMPPUTils.getXMPPUtils();

const LOG_ID = "OPTIONS - ";

class Options {
	public _logger: Logger;
	public _options: any; //OptionsType;
	public _hasCredentials: any;
	public _hasApplication: any;
	public _httpOptions: any;
	public _xmppOptions: any;
	public _s2sOptions: any;
	public _restOptions: any;
	public _proxyoptions: any;
	public _imOptions: any;
	public _applicationOptions: any;
	public _withXMPP: any;
	public _withS2S: any;
	public _CLIMode: any;
	public _servicesToStart: any;
	private _testOutdatedVersion: boolean;
	private _testDNSentry: boolean;
	private _autoReconnectIgnoreErrors: boolean;
	private _httpoverxmppserver: boolean;
    private _concurrentRequests: number;
    private _intervalBetweenCleanMemoryCache: number;
    private _requestsRate: any;
    private _configIniData: any;

    constructor(_options: any, _logger: Logger) {
        this._logger = _logger;
        this._options = _options;
        this._hasCredentials = true;
        this._hasApplication = true;
        this._withXMPP = true;
        this._withS2S = false;
        this._CLIMode = true;
        this._testOutdatedVersion = true;
        this._testDNSentry = true;
        this._autoReconnectIgnoreErrors = false;
        this._httpoverxmppserver = false;
        this._intervalBetweenCleanMemoryCache = 1000 * 60 * 60 * 6; // Every 6 hours
        this._configIniData = {};
    }

    parse() {
        this._configIniData = loadConfigFromIniFile();
        if (!this._options) {
            this._logger.log("error", LOG_ID + "(constructor) No 'options' parameter. Can't sign-in. Check the documentation to configure it");
            this._hasCredentials = false;
        }

        if (!this._options.rainbow || !this._options.rainbow.host) {
            this._logger.log("warn", LOG_ID + "(constructor) 'host' property is not defined. Use default: 'sandbox'. Check the documentation to configure it");
            this._options.rainbow = {host: "sandbox", mode: "xmpp"};
        }

        if (!this._options.proxy) {
            this._logger.log("debug", LOG_ID + "(constructor) 'proxy' property is not defined. Use default: no proxy. Check the documentation to enable it");
            this._options.proxy = {};
           // this._options.proxy = {host: "", protocol: "http", port: 80, user : undefined, password : undefined, secureProtocol: undefined};
        }

        if (!this._options.credentials) {
            this._logger.log("error", LOG_ID + "(constructor) 'credentials' property is not defined. Can't sign-in. Check the documentation to configure it");
            this._hasCredentials = false;
        } else if (( this._options.credentials.login || this._options.credentials.password ) && isNotDefined(this._options.credentials.apikey)) {
            this._logger.log("info", LOG_ID + "(constructor) 'credentials' property is defined. login.");
            this._hasCredentials = true;
        } else if (( !this._options.credentials.login || !this._options.credentials.password ) && isDefined(this._options.credentials.apikey)) {
            this._logger.log("info", LOG_ID + "(constructor) 'credentials' property is defined. apikey.");
            this._hasCredentials = true;
        } else if (( !this._options.credentials.login || !this._options.credentials.password ) && isNotDefined(this._options.credentials.apikey)) {
            this._logger.log("error", LOG_ID + "(constructor) 'login' or 'password' is not defined. Can't sign-in. Check the documentation to configure it");
            this._hasCredentials = false;
        } else if (isNotDefined(this._options.credentials.apikey)) {
            this._logger.log("error", LOG_ID + "(constructor) 'apikey' is not defined. Can't sign-in. Check the documentation to configure it");
            this._hasCredentials = false;
        }

        if (!this._options.application) {
            this._logger.log("error", LOG_ID + "(constructor) 'application' property is not defined. Can't sign-in. Check the documentation to configure it");
            this._hasApplication = false;
        } else if (!this._options.application.appID || !this._options.application.appSecret) {
            this._logger.log("error", LOG_ID + "(constructor) 'appId' or 'appSecret' is not defined. Can't sign-in. Check the documentation to configure it");
            this._hasApplication = false;
        }

        this._httpOptions = this._getHTTPOptions();
        this._xmppOptions = this._getXMPPOptions();
        this._s2sOptions = this._getS2SOptions();
        this._restOptions = this._getRESTOptions();
        this._proxyoptions = this._getProxyOptions();
        this._imOptions = this._getIMOptions();
        this._applicationOptions = this._getApplicationsOptions();

        let mode = this._getModeOption();
        // Disable the xmpp mode if the ApiKey is used to connect SDK.
        if (this._hasCredentials === true) {
            if (isNotDefinedOrEmpty(this._options.credentials.login) && isNotDefinedOrEmpty(this._options.credentials.password) && isDefinedAndNotEmpty(this._options.credentials.apikey)) {
                mode = "cli";
            }
        }
        this._withXMPP = mode==="xmpp";
        this._withS2S = mode === "s2s";
        this._CLIMode = mode === "cli";
        this._servicesToStart = this._getservicesToStart();
        this._testOutdatedVersion = this._gettestOutdatedVersion();
        this._testDNSentry = this._gettestDNSentry();
        this._autoReconnectIgnoreErrors = this._getautoReconnectIgnoreErrors();
        this._httpoverxmppserver = this._gethttpoverxmppserver();
        this._intervalBetweenCleanMemoryCache = this._getintervalBetweenCleanMemoryCache();
        //this._concurrentRequests = this._getConcurrentRequestsOption();
        this._requestsRate = this._getRequestsRateOption();
        saveConfigFromIniFile(this._configIniData);
    }

    get testOutdatedVersion(): boolean {
        return this._testOutdatedVersion;
    }

    set testOutdatedVersion(value: boolean) {
        this._testOutdatedVersion = toBoolean(value);
    }

    get testDNSentry(): boolean {
        return this._testDNSentry;
    }

    set testDNSentry(value: boolean) {
        this._testDNSentry = toBoolean(value);
    }

    get autoReconnectIgnoreErrors(): boolean {
        return this._autoReconnectIgnoreErrors;
    }

    set autoReconnectIgnoreErrors(value: boolean) {
        this._autoReconnectIgnoreErrors = toBoolean(value);
    }

    get testhttpoverxmppserver(): boolean {
        return this._httpoverxmppserver;
    }

    set testhttpoverxmppserver(value: boolean) {
        this._httpoverxmppserver = toBoolean(value);
    }

    get intervalBetweenCleanMemoryCache(): number {
        return this._intervalBetweenCleanMemoryCache;
    }

    set intervalBetweenCleanMemoryCache(value: number) {
        this._intervalBetweenCleanMemoryCache = value;
    }

    get servicesToStart () {
        return this._servicesToStart;
    }

    get httpOptions() {
        return this._httpOptions;
    }

    get xmppOptions() {
        return this._xmppOptions;
    }

    get s2sOptions() {
        return this._s2sOptions;
    }

    get restOptions() {
        return this._restOptions;
    }

    get proxyOptions() {
        return this._proxyoptions;
    }

    get imOptions() {
        return this._imOptions;
    }

    get applicationOptions() {
        return this._applicationOptions;
    }

    get hasCredentials() {
        return this._hasCredentials;
    }

    get hasApplication() {
        return this._hasApplication;
    }

    get useXMPP() {
        return this._withXMPP;
    }

    get useS2S() {
        return this._withS2S;
    }

    get useCLIMode() {
        return this._CLIMode;
    }

    get credentials() {
        return this._options.credentials;
    }

    get concurrentRequests(): number {
        return this._concurrentRequests;
    }

    get requestsRate(): {
        "useRequestRateLimiter": number,
        "maxReqByIntervalForRequestRate": number,
        "intervalForRequestRate": number, 
        "timeoutRequestForRequestRate": number } {
        return this._requestsRate;
    }

    _gettestOutdatedVersion() {
        if ( isDefined(this._options["testOutdatedVersion"]) ) {
            return toBoolean(this._options.testOutdatedVersion);
        } else {
            return config.testOutdatedVersion;
        }
    }

    _gettestDNSentry() {
        if ( isDefined(this._options["testDNSentry"] ) ) {
            return toBoolean(this._options.testDNSentry);
        } else {
            return config.testDNSentry;
        }
    }

    _getautoReconnectIgnoreErrors() {
        if ( isDefined(this._options["autoReconnectIgnoreErrors"]) ) {
            return toBoolean(this._options.autoReconnectIgnoreErrors);
        } else {
            return config.autoReconnectIgnoreErrors;
        }
    }

    _gethttpoverxmppserver() {
        if ( isDefined(this._options["httpoverxmppserver"]) ) {
            return toBoolean(this._options.httpoverxmppserver);
        } else {
            return config.httpoverxmppserver;
        }
    }

    _getintervalBetweenCleanMemoryCache() {
        if ( isDefined(this._options["intervalBetweenCleanMemoryCache"])) {
            return this._options.intervalBetweenCleanMemoryCache;
        } else {
            return config.intervalBetweenCleanMemoryCache;
        }
    }

    _getservicesToStart() {
        let svceToStart = {};
        if (!this._options.servicesToStart) {
            svceToStart = Object.assign({},config.servicesToStart);
        } else {
            svceToStart = Object.assign({},config.servicesToStart);
            // Read each property one by one in the option parameter. To avoid missed service config.
            if ( typeof(this._options.servicesToStart) === 'object') {
                Object.keys(this._options.servicesToStart).forEach((key) => {
                    if (!svceToStart[key]) {
                        this._logger.log("warn", LOG_ID + "(_getservicesToStart) the service ", key, " is requested have start up to be configured, but it is not defined in default config.");
                        svceToStart[key] = {};
                    }
                    svceToStart[key].start_up = "start_up" in this._options.servicesToStart[key] ? this._options.servicesToStart[key].start_up : config.servicesToStart[key].start_up;
                    svceToStart[key].optional = "optional" in this._options.servicesToStart[key] ? this._options.servicesToStart[key].optional : config.servicesToStart[key].optional;
                });
            } // Else the options parameter is not well completed, so keep default values to start services.
        }

        return svceToStart;
    }

    _isOfficialRainbow () {
        return (this._options.rainbow.host === "official" || this._options.rainbow.host === "openrainbow.com");
        //return (this._options.rainbow.host === "official" );
    }

    _getHTTPOptions() {
        let httpOptions = config.sandbox.http;

        switch (this._options.rainbow.host) {
            case "openrainbow.com":
            case "official":
                httpOptions = config.official.http;
                this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow Official platform");
                break;
            case "sandbox":
                httpOptions = config.sandbox.http;
                this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow Sandbox platform");
                break;
            default:
                httpOptions = config.any.http;
                httpOptions.host = this._options.rainbow.host;
                this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow " + this._options.rainbow.host + " platform");
                break;
        }
        return httpOptions;
    }

    _getXMPPOptions() {
        let xmppOptions = config.sandbox.xmpp;

        switch (this._options.rainbow.host) {
            case "openrainbow.com":
            case "official":
                xmppOptions = config.official.xmpp;
                this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow Official platform");
                break;
            case "sandbox":
                xmppOptions = config.sandbox.xmpp;
                this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow Sandbox platform");
                break;
            default:
                xmppOptions = config.any.xmpp;
                xmppOptions.host = this._options.rainbow.host;
                if ( this._options.xmpp && this._options.xmpp.protocol ) {  xmppOptions.protocol = this._options.xmpp.protocol; }
                if ( this._options.xmpp && this._options.xmpp.port) { xmppOptions.port = this._options.xmpp.port; }
                this._logger.log("warn", LOG_ID + "(constructor) Be careful, an unofficial Rainbow core is used : " + JSON.stringify(xmppOptions));
                this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow " + this._options.rainbow.host + " platform");
                break;
        }
        if ( this._options.xmpp ) {
            if (isDefined(this._options.xmpp.raiseLowLevelXmppInEvent)) {
                xmppOptions.raiseLowLevelXmppInEvent = toBoolean(this._options.xmpp.raiseLowLevelXmppInEvent);
            }
            if (isDefined(this._options.xmpp.xmppRessourceName)) {
                xmppOptions.xmppRessourceName = this._options.xmpp.xmppRessourceName;
            }
            if (isDefined(this._options.xmpp.raiseLowLevelXmppOutReq)) {
                xmppOptions.raiseLowLevelXmppOutReq = toBoolean(this._options.xmpp.raiseLowLevelXmppOutReq);
            }
            if (isDefined(this._options.xmpp.maxIdleTimer)) {
                xmppOptions.maxIdleTimer = this._options.xmpp.maxIdleTimer;
            }
            if (isDefined(this._options.xmpp.timeBetweenXmppRequests)) {
                xmppOptions.timeBetweenXmppRequests = this._options.xmpp.timeBetweenXmppRequests;
            }
            if (isDefined(this._options.xmpp.maxPendingAsyncLockXmppQueue)) {
                xmppOptions.maxPendingAsyncLockXmppQueue = this._options.xmpp.maxPendingAsyncLockXmppQueue;
            }
            if (isDefined(this._options.xmpp.maxPingAnswerTimer)) {
                xmppOptions.maxPingAnswerTimer = this._options.xmpp.maxPingAnswerTimer;
            }
            if (isDefined(this._options.xmpp.stanzaMaxLength)) {
                xmppOptions.stanzaMaxLength = this._options.xmpp.stanzaMaxLength;
            }
              /*
        let paramArray = [];
        paramArray.push(xmppOptions);

        updateObjectPropertiesFromAnOtherObject(paramArray, this._options.xmpp);
        // */
        }
        if (!xmppOptions.xmppRessourceName ) {
            if (isDefined(this._configIniData.xmppRessourceName)) {
                xmppOptions.xmppRessourceName = this._configIniData.xmppRessourceName;
            } else {
                xmppOptions.xmppRessourceName = xmppUtils.generateRandomID();
                this._configIniData.xmppRessourceName = xmppOptions.xmppRessourceName;
            }
        }
        return xmppOptions;
    }

    _getS2SOptions() {
        let s2sOptions = config.sandbox.s2s;

        switch (this._options.rainbow.host) {
            case "openrainbow.com":
            case "official":
                s2sOptions = config.official.s2s;
                if ( this._options.s2s && this._options.s2s.hostCallback ) {  s2sOptions.hostCallback = this._options.s2s.hostCallback; }
                if ( this._options.s2s && this._options.s2s.locallistenningport ) {  s2sOptions.locallistenningport = this._options.s2s.locallistenningport; }
                if ( this._options.s2s && this._options.s2s.expressEngine) {  s2sOptions.expressEngine = this._options.s2s.expressEngine; }
                this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow Official platform");
                break;
            case "sandbox":
                s2sOptions = config.sandbox.s2s;
                if ( this._options.s2s && this._options.s2s.hostCallback ) {  s2sOptions.hostCallback = this._options.s2s.hostCallback; }
                if ( this._options.s2s && this._options.s2s.locallistenningport ) {  s2sOptions.locallistenningport = this._options.s2s.locallistenningport; }
                if ( this._options.s2s && this._options.s2s.expressEngine) {  s2sOptions.expressEngine = this._options.s2s.expressEngine; }
                this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow Sandbox platform");
                break;
            default:
                s2sOptions = config.any.s2s;
                if ( this._options.s2s && this._options.s2s.hostCallback ) {  s2sOptions.hostCallback = this._options.s2s.hostCallback; }
                if ( this._options.s2s && this._options.s2s.locallistenningport ) {  s2sOptions.locallistenningport = this._options.s2s.locallistenningport; }
                if ( this._options.s2s && this._options.s2s.expressEngine) {  s2sOptions.expressEngine = this._options.s2s.expressEngine; }
                this._logger.log("warn", LOG_ID + "(constructor) Be careful, an unofficial Rainbow core is used : " + JSON.stringify(s2sOptions));
                this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow " + this._options.rainbow.host + " platform");
                break;
        }
        return s2sOptions;
    }

    _getRESTOptions() {
        let restOptions = config.any.rest;

        if ("rest" in this._options) {

            let restArray = [];
            restArray.push(restOptions);

            updateObjectPropertiesFromAnOtherObject(restArray, this._options.rest);

            //restOptions = this._options.rest;
        }
        return restOptions;
    }

    _getModeOption() {

        let mode = config.mode;

        if ("rainbow" in this._options && "mode" in this._options.rainbow) {
            switch (this._options.rainbow.mode) {
                case "xmpp":
                case "s2s":
                case "hook":
                case "cli":
                    mode = this._options.rainbow.mode;
                    break;
                default:
                    mode = config.mode;
                    break;
            }
        }
        return mode;
    }

/*
    _getConcurrentRequestsOption() {

        let concurrentRequests = config.concurrentRequests;

        if ("rainbow" in this._options && "concurrentRequests" in this._options.rainbow) {
            concurrentRequests = this._options.rainbow.concurrentRequests;
        }
        return concurrentRequests;
    }
// */
    
    _getRequestsRateOption() {
        let requestsRate = config.requestsRate;

        if ("rainbow" in this._options && "requestsRate" in this._options) {
            requestsRate = this._options.requestsRate;
        }
        return requestsRate;
    }

    _getProxyOptions() {

        let proxyOptions = {
            "protocol": "http",
            "host": "",
            "port": 80,
            "user": undefined,
            "password": undefined,
            "secureProtocol": undefined
        };

        if (!("host" in this._options.proxy)) {
            this._logger.log("warn", LOG_ID + "(constructor) 'host' property is not defined. No proxy will be used");
            delete proxyOptions["host"];
        }
        else {
            proxyOptions.host = this._options.proxy.host;
        }
        if (!("port" in this._options.proxy)) {
            this._logger.log("debug", LOG_ID + "(constructor) 'port' property is not defined. Use default 80");
            delete proxyOptions["port"];
        }
        else {
            proxyOptions.port = this._options.proxy.port;
        }
        if (!("protocol" in this._options.proxy)) {
            this._logger.log("debug", LOG_ID + "(constructor) 'protocol' property not defined. Use default 'http'");
            delete proxyOptions["protocol"];
        }
        else {
            proxyOptions.protocol = this._options.proxy.protocol;
        }
        if (!("user" in this._options.proxy)) {
            this._logger.log("debug", LOG_ID + "(constructor) 'user' property not defined. No authentication. ");
            delete proxyOptions["user"];
        }
        else {
            proxyOptions.user = this._options.proxy.user;
        }
        if (!("password" in this._options.proxy)) {
            this._logger.log("debug", LOG_ID + "(constructor) 'password' property not defined. No authentication.");
            delete proxyOptions["password"];
        }
        else {
            proxyOptions.password = this._options.proxy.password;
        }
        if (!("secureProtocol" in this._options.proxy)) {
            this._logger.log("debug", LOG_ID + "(constructor) 'secureProtocol' property not defined. No SSL3.");
            delete proxyOptions["secureProtocol"];
        }
        else {
            proxyOptions.secureProtocol = this._options.proxy.secureProtocol;
        }

        return proxyOptions;
    }

    _getIMOptions() {

        let optionsIM = {
            "sendReadReceipt":true,
            "messageMaxLength" : 16384, // Max stanza size on server is 18432
            "sendMessageToConnectedUser": false,
            "conversationsRetrievedFormat": "small",
            "storeMessages": false,
            "copyMessage": true,
            "nbMaxConversations": 15,
            "rateLimitPerHour": 10000,
            "messagesDataStore": DataStoreType.UsestoreMessagesField,
            "autoInitialGetBubbles": true,
            "autoInitialBubblePresence": true,
            "maxBubbleJoinInProgress": 10,
            "autoInitialBubbleFormat": "full",
            "autoInitialBubbleUnsubscribed": false,
            "autoLoadConversations": true,
            "autoLoadConversationHistory": false,
            "autoLoadContacts": true,
            "autoInitialLoadContactsInfoBulk": true,
            "autoLoadCallLog": false,
            "forceHistoryGetContactFromServer": false,
            "enableCarbon": true,
            "enablesendurgentpushmessages": false,
            "useMessageEditionAndDeletionV2": true,
            "storeMessagesInConversation": true,
            "maxMessagesStoredInConversation": 1000
        };

        optionsIM.sendReadReceipt = isDefined(config.im.sendReadReceipt) ? toBoolean(config.im.sendReadReceipt) : this._options.im.sendReadReceipt;
        optionsIM.messageMaxLength = isDefined(this._options.im.messageMaxLength) ? this._options.im.messageMaxLength : config.im.messageMaxLength;
        optionsIM.sendMessageToConnectedUser = isDefined(this._options.im.sendMessageToConnectedUser) ? toBoolean(this._options.im.sendMessageToConnectedUser) : config.im.sendMessageToConnectedUser;
        optionsIM.conversationsRetrievedFormat = isDefined(this._options.im.conversationsRetrievedFormat) ? this._options.im.conversationsRetrievedFormat : config.im.conversationsRetrievedFormat;
        optionsIM.storeMessages = isDefined(this._options.im.storeMessages) ? toBoolean(this._options.im.storeMessages) : config.im.storeMessages;
        optionsIM.copyMessage = isDefined(this._options.im.copyMessage) ? toBoolean(this._options.im.copyMessage) : config.im.copyMessage;
        optionsIM.nbMaxConversations = isDefined(this._options.im.nbMaxConversations) ? this._options.im.nbMaxConversations : config.im.nbMaxConversations;
        optionsIM.rateLimitPerHour = isDefined(this._options.im.rateLimitPerHour) ? this._options.im.rateLimitPerHour : config.im.rateLimitPerHour;
        optionsIM.messagesDataStore = isDefined(this._options.im.messagesDataStore) ? this._options.im.messagesDataStore : config.im.messagesDataStore;
        optionsIM.autoInitialGetBubbles = isDefined(this._options.im.autoInitialGetBubbles) ? toBoolean(this._options.im.autoInitialGetBubbles) : config.im.autoInitialGetBubbles;
        optionsIM.autoInitialBubblePresence = isDefined(this._options.im.autoInitialBubblePresence) ? toBoolean(this._options.im.autoInitialBubblePresence) : config.im.autoInitialBubblePresence;
        optionsIM.maxBubbleJoinInProgress = isDefined(this._options.im.maxBubbleJoinInProgress) ? this._options.im.maxBubbleJoinInProgress : config.im.maxBubbleJoinInProgress;
        optionsIM.autoInitialBubbleFormat = isDefined(this._options.im.autoInitialBubbleFormat) ? this._options.im.autoInitialBubbleFormat : config.im.autoInitialBubbleFormat;
        optionsIM.autoInitialBubbleUnsubscribed = isDefined(this._options.im.autoInitialBubbleUnsubscribed) ? toBoolean(this._options.im.autoInitialBubbleUnsubscribed) : config.im.autoInitialBubbleUnsubscribed;
        optionsIM.autoLoadConversations = isDefined(this._options.im.autoLoadConversations) ? toBoolean(this._options.im.autoLoadConversations) : config.im.autoLoadConversations;
        optionsIM.autoLoadConversationHistory = isDefined(this._options.im.autoLoadConversationHistory) ? toBoolean(this._options.im.autoLoadConversationHistory) : config.im.autoLoadConversationHistory;
        optionsIM.autoLoadContacts = isDefined(this._options.im.autoLoadContacts) ? toBoolean(this._options.im.autoLoadContacts) : config.im.autoLoadContacts;
        optionsIM.autoInitialLoadContactsInfoBulk = isDefined(this._options.im.autoInitialLoadContactsInfoBulk) ? toBoolean(this._options.im.autoInitialLoadContactsInfoBulk) : config.im.autoInitialLoadContactsInfoBulk;
        optionsIM.autoLoadCallLog = isDefined(this._options.im.autoLoadCallLog) ? toBoolean(this._options.im.autoLoadCallLog) : config.im.autoLoadCallLog;
        optionsIM.forceHistoryGetContactFromServer = isDefined(this._options.im.forceHistoryGetContactFromServer) ? toBoolean(this._options.im.forceHistoryGetContactFromServer) : config.im.forceHistoryGetContactFromServer;
        optionsIM.enableCarbon = isDefined(this._options.im.enableCarbon) ? toBoolean(this._options.im.enableCarbon) : config.im.enableCarbon;
        optionsIM.enablesendurgentpushmessages = isDefined(this._options.im.enablesendurgentpushmessages) ? toBoolean(this._options.im.enablesendurgentpushmessages) : config.im.enablesendurgentpushmessages;
        optionsIM.useMessageEditionAndDeletionV2 = isDefined(this._options.im.useMessageEditionAndDeletionV2) ? toBoolean(this._options.im.useMessageEditionAndDeletionV2) : config.im.useMessageEditionAndDeletionV2;
        optionsIM.storeMessagesInConversation = isDefined(this._options.im.storeMessagesInConversation) ? toBoolean(this._options.im.storeMessagesInConversation) : config.im.storeMessagesInConversation;
        optionsIM.maxMessagesStoredInConversation = isDefined(this._options.im.maxMessagesStoredInConversation) ? this._options.im.maxMessagesStoredInConversation : config.im.maxMessagesStoredInConversation;

        return optionsIM;
    }

    _getApplicationsOptions() {
        let applicationOptions = {
            "appID": "",
            "appSecret": ""
        };

        if ("application" in this._options) {
            if (!("appID" in this._options.application)) {
                this._logger.log("warn", LOG_ID + "(constructor) 'appID' property is not defined. No application ID will be used");
            }
            else {
                applicationOptions.appID = this._options.application.appID;
            }

            if (!("appSecret" in this._options.application)) {
                this._logger.log("warn", LOG_ID + "(constructor) 'appSecret' property is not defined. No application Secret will be used");
            }
            else {
                applicationOptions.appSecret = this._options.application.appSecret;
            }

        }
        else {
            this._logger.log("warn", LOG_ID + "(constructor) 'appID' property is not defined. No application ID will be used");
            this._logger.log("warn", LOG_ID + "(constructor) 'appSecret' property is not defined. No application Secret will be used");
        }

        return applicationOptions;
    }

    /*
    get messageMaxLength () {
        let messageMaxLength = 16384;

        messageMaxLength = this._options.im.messageMaxLength ? this._options.im.messageMaxLength : config.im.messageMaxLength;

        return messageMaxLength
    }

     */

}
module.exports.Options = Options;
export {Options};
