"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var api_1 = require("../../protocol/api");
var rxjs_1 = require("rxjs");
var abstract_com_protocol_1 = require("./abstract-com-protocol");
var job_queue_1 = require("../../util/job-queue");
// import { _throw } from "rxjs/observable/throw";
var observable_helper_1 = require("../../util/observable-helper");
var format_helper_1 = require("../../core/format/format-helper");
// import "rxjs/observable/throw";
/**
 *
 */
var QueueComProtocol = /** @class */ (function (_super) {
    __extends(QueueComProtocol, _super);
    function QueueComProtocol() {
        var _this = _super.call(this) || this;
        _this._queue = new job_queue_1.JobQueue();
        return _this;
    }
    QueueComProtocol.prototype._send = function (data, options) {
        var _this = this;
        // console.debug('QueueComProtocol', '_send()', '-------------------------');
        if (!this.isConnected()) {
            return rxjs_1.from(Promise.reject(new Error("Device is not connected"))); // TODO can use throwObservable instead
        }
        return rxjs_1.from(this
            .write(data)
            .then(function () {
            return _this.read();
        }));
    };
    /**
     *
     * @param data
     * @param options
     */
    QueueComProtocol.prototype.send = function (data, options) {
        var _this = this;
        console.debug("QueueComProtocol", "::send() ENQUEUE request (" + data.length + " bytes) " + format_helper_1.FormatHelper.toHexString(data) + ". Queue position: " + this._queue.size);
        if (true) {
            data = data.slice(0);
        }
        var observable = this._enqueue(function () {
            var timeout = options ? options.timeout : _this._options.send.timeout;
            console.debug("QueueComProtocol", "::send() EXECUTE request  (" + data.length + " bytes) " + format_helper_1.FormatHelper.toHexString(data) + " (timeout: " + timeout + ") ");
            return observable_helper_1.ObservableHelper.timeout(_this._send(data, options), timeout);
        });
        return observable;
    };
    QueueComProtocol.prototype._enqueue = function (startJob) {
        return this._queue.add(startJob);
    };
    /**
     * Connect with timeout
     *
     * If connect has already been called or is in progress / no further action
     *
     * @param options
     */
    QueueComProtocol.prototype.connect = function (options) {
        var _this = this;
        if (this.connectionState === api_1.ConnectionState.CONNECTED) {
            console.warn("QueueComProtocol is already connected");
            return rxjs_1.of(null);
        }
        if (this.connectionState == api_1.ConnectionState.CONNECTING) {
            return this._connect$;
        }
        this._connect$ = observable_helper_1.ObservableHelper.timeout(this._connect(options), options ? options.timeout : this._options.connect.timeout);
        this.setConnectionState(api_1.ConnectionState.CONNECTING);
        this._connectionSubscription = this._connect$.subscribe(function () {
            _this.setConnectionState(api_1.ConnectionState.CONNECTED);
        }, function (error) {
            _this.setConnectionState(api_1.ConnectionState.DISCONNECTED);
        });
        return this._connect$;
    };
    QueueComProtocol.prototype.disconnect = function (options) {
        var _this = this;
        if (this.connectionState === api_1.ConnectionState.DISCONNECTED) {
            return rxjs_1.of(null);
        }
        if (this.connectionState == api_1.ConnectionState.DISCONNECTING) {
            return this._disconnect$;
        }
        this._connect$ = undefined;
        this._disconnect$ = observable_helper_1.ObservableHelper.timeout(this._disconnect(options), options ? options.timeout : this._options.disconnect.timeout);
        this.setConnectionState(api_1.ConnectionState.DISCONNECTING);
        this._disconnect$.subscribe(function () {
            _this.setConnectionState(api_1.ConnectionState.DISCONNECTED);
        }, function (error) {
            _this.setConnectionState(api_1.ConnectionState.DISCONNECTED);
        });
        return this._disconnect$;
    };
    return QueueComProtocol;
}(abstract_com_protocol_1.AbstractComProtocol));
exports.QueueComProtocol = QueueComProtocol;
