var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        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 extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __awaiter = (this && this.__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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import { QueueComProtocol } from '@iotize/tap/protocol/core';
import { of, Subject } from 'rxjs';
import { delay, first } from 'rxjs/operators';
import { debug } from '../debug';
import { MockRouter } from './mock-router';
var TAG = 'MockProtocol';
export function createMockProtocol() {
    return new MockProtocol();
}
/**
 *
 * <p>
 * This is a mock com protocol for testing only
 * <p>
 * We can simulate iotize response according to the request message
 */
var MockProtocol = /** @class */ (function (_super) {
    __extends(MockProtocol, _super);
    function MockProtocol() {
        var _this = _super.call(this) || this;
        _this.mockOptions = {
            connect: {
                delay: 100
            },
            disconnect: {
                delay: 100
            },
            write: {
                delay: 1
            }
        };
        _this.input = new Subject();
        _this.output = new Subject();
        _this._router = new MockRouter();
        return _this;
        // this.connectDelay = 2000;
        // this.disconnectDelay = 2000;
        // this.callback = callback;
        // this.lastReceivedData = new Uint8Array(0);
        // this.configuration = new Configuration();
        // this.configuration.connectionTimeoutMillis = 3000;
        // this.configuration.sendTimeoutMillis = 3000;
    }
    MockProtocol.MIRROR = function () {
        var mockProtocol = new MockProtocol();
        mockProtocol.input
            .subscribe(function (input) {
            mockProtocol.setOutputData(input);
        });
        // mockProtocol.router.addRoute(
        //     (command: Uint8Array) => {
        //         return true;
        //     },
        //     (request: Uint8Array) => {
        //         return request;
        //     }
        // );
        return mockProtocol;
    };
    // /**
    //  * Create a new instance from roote mapping
    //  */
    // public static createFromRoutes(map: RouteMapping): MockProtocol {
    //     const mockProtocol = new MockProtocol();
    //     mockProtocol.router.addRoutes(map);
    //     return mockProtocol;
    // }
    // public get router(): MockRouter {
    //     return this._router;
    // }
    MockProtocol.prototype.setConnectionState = function (connectionState) {
        debug(TAG, "setConnectionState: " + connectionState);
        this.connectionState = connectionState;
        return this;
    };
    MockProtocol.prototype.setConnectDelay = function (connectDelay) {
        this.mockOptions.connect.delay = connectDelay;
        return this;
    };
    MockProtocol.prototype.getDisconnectDelay = function () {
        return this.mockOptions.disconnect.delay;
    };
    MockProtocol.prototype.setDisconnectDelay = function (disconnectDelay) {
        this.mockOptions.disconnect.delay = disconnectDelay;
        return this;
    };
    MockProtocol.prototype.setOutputData = function (inputData) {
        this.lastTranseiveData = inputData;
        this.output.next(inputData);
    };
    MockProtocol.prototype.setInputData = function (outputData) {
        this.lastReceivedData = outputData;
        this.input.next(outputData);
    };
    MockProtocol.prototype.setCallback = function (callback) {
        this.callback = callback;
    };
    MockProtocol.prototype._connect = function (options) {
        return of(undefined).pipe(delay(this.mockOptions.connect.delay));
    };
    MockProtocol.prototype._disconnect = function (options) {
        return of(undefined).pipe(delay(this.mockOptions.disconnect.delay));
    };
    MockProtocol.prototype.write = function (request) {
        return __awaiter(this, void 0, void 0, function () {
            var err_1;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 5, , 6]);
                        if (!this.callback) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.callback.beforeWrite(request)];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2:
                        // this.lastReceivedData = request;
                        // const response = this.router.findRoute(request);
                        // if (!response) {
                        //     throw new Error(`Not route for request ${bufferToHexString(request)}`)
                        // }
                        // debug(
                        //     TAG,
                        //     'MockProtocol',
                        //     'Mocking response for ' + request + ' => ' + response
                        // );
                        // var result = this.responseEncoder.encode(response);
                        this.setInputData(request);
                        if (!this.callback) return [3 /*break*/, 4];
                        return [4 /*yield*/, this.callback.afterWrite(request)];
                    case 3:
                        _a.sent();
                        _a.label = 4;
                    case 4: return [2 /*return*/, new Promise(function (resolve) {
                            return setTimeout(resolve, _this.mockOptions.write.delay);
                        })];
                    case 5:
                        err_1 = _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                return setTimeout(function () { return reject(err_1); }, _this.mockOptions.write.delay);
                            })];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    MockProtocol.prototype.read = function () {
        try {
            if (this.callback) {
                this.callback.beforeRead();
            }
            return this.output.pipe(first()).toPromise();
            // while (!this.hasNewData()) {
            //     // TODO wait ??
            // }
            // if (this.lastTranseiveData) {
            //     const result = of(this.lastTranseiveData);
            //     if (this.callback) {
            //         this.callback.afterRead(result);
            //     }
            //     return result.toPromise();
            // } else {
            //     return Promise.reject(new Error('Read timeout'));
            // }
        }
        catch (err) {
            return Promise.reject(err);
        }
    };
    return MockProtocol;
}(QueueComProtocol));
export { MockProtocol };
//    public addOnRequestListener() {
//        this.mOnRequestListener =
//    }
//    public interface onRequestListener{
//        onRequest(RequestMessage request);
//    }
//# sourceMappingURL=data:application/json;base64, 