import rxjs from 'rxjs';
import operators from 'rxjs/operators';
import common from '@iotize/common';
import deviceClient from '@iotize/device-client.js';

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function commonjsRequire () {
	throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}

function unwrapExports (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

function getCjsExportFromNamespace (n) {
	return n && n['default'] || n;
}

var debug = createCommonjsModule(function (module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

const prefix = '@iotize:device-client.js:keepalive';
exports.debug = common.createDebugger(prefix);

});

var debug$1 = unwrapExports(debug);
var debug_1 = debug.debug;

var keepAlive = createCommonjsModule(function (module, exports) {
"use strict";
var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });



exports.DEFAULT_KEEP_ALIVE_PERIOD_MS = 5000;
const TAG = 'KeepAliveEngine';
class KeepAliveEngine {
    constructor(tap, options) {
        this.tap = tap;
        this.options = options;
        this._lastResponseTime = 0;
        this._isStopped = true;
        this._events = new rxjs.Subject();
        debug.debug(TAG, 'new KeepAliveEngine()');
        this.tap.client.addInterceptor((req, handle) => {
            return handle.handle(req).pipe(operators.tap({
                next: () => {
                    debug.debug(TAG, 'update last response time', this._lastResponseTime, '=>', new Date().getTime());
                    this._lastResponseTime = new Date().getTime();
                }
            }));
        });
    }
    get events() {
        return this._events.asObservable();
    }
    get running() {
        return !this._isStopped;
    }
    start() {
        this._isStopped = false;
        if (!this.timeoutId) {
            this._setupNextTimeout(0);
        }
        this._events.next({
            type: 'start'
        });
    }
    stop() {
        this._isStopped = true;
        if (this.timeoutId) {
            clearTimeout(this.timeoutId);
            this.timeoutId = undefined;
        }
        this._events.next({
            type: 'stop'
        });
    }
    _setupNextTimeout(timeoutMs) {
        if (this._isStopped) {
            return;
        }
        this._events.next({
            type: 'rescheduleKeepAlive',
            timeout: timeoutMs
        });
        this.timeoutId = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
            if (this.tap.isConnected()) {
                let remainingTime = this.options.period - elapsedTime(this._lastResponseTime);
                if (remainingTime > 0) {
                    debug.debug(TAG, 'Reschedule keep alive in ', remainingTime);
                    this._setupNextTimeout(remainingTime);
                }
                else {
                    debug.debug(TAG, 'Running keep alive');
                    try {
                        this._events.next({
                            type: 'tick'
                        });
                        yield this.tap.service.interface.keepAlive();
                    }
                    catch (err) {
                        this._events.next({
                            type: 'error',
                            error: err
                        });
                    }
                    this._setupNextTimeout(this.options.period);
                }
            }
        }), timeoutMs);
    }
}
exports.KeepAliveEngine = KeepAliveEngine;
function elapsedTime(time) {
    return new Date().getTime() - time;
}

});

var keepAlive$1 = unwrapExports(keepAlive);
var keepAlive_1 = keepAlive.DEFAULT_KEEP_ALIVE_PERIOD_MS;
var keepAlive_2 = keepAlive.KeepAliveEngine;

var tapExtension = createCommonjsModule(function (module, exports) {
"use strict";
var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });



Object.defineProperty(deviceClient.IoTizeDevice.prototype, 'keepAlive', {
    get() {
        if (!this._keepAliveTask) {
            debug.debug(`Create keep alive engine`);
            this._keepAliveTask = new keepAlive.KeepAliveEngine(this, {
                period: keepAlive.DEFAULT_KEEP_ALIVE_PERIOD_MS
            });
        }
        return this._keepAliveTask;
    },
    enumerable: false,
    configurable: true
});
deviceClient.IoTizeDevice.prototype.setupKeepAliveFromConfig = function () {
    return __awaiter(this, void 0, void 0, function* () {
        let periodInSeconds = (yield this.service.interface.getHostInactivityPeriod()).body();
        this.keepAlive.options.period = periodInSeconds * 1000;
        this.keepAlive.start();
    });
};

});

var tapExtension$1 = unwrapExports(tapExtension);

var public_api = createCommonjsModule(function (module, exports) {
"use strict";
function __export(m) {
    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(keepAlive);


});

var public_api$1 = unwrapExports(public_api);

var iotizeDeviceClient_jsKeepAlive = createCommonjsModule(function (module, exports) {
"use strict";
/**
 * Generated bundle index. Do not edit.
 */
function __export(m) {
    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(public_api);

});

var iotizeDeviceClient_jsKeepAlive$1 = unwrapExports(iotizeDeviceClient_jsKeepAlive);

export default iotizeDeviceClient_jsKeepAlive$1;
//# sourceMappingURL=iotize-device-client.js-keep-alive.js.map
