(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@iotize/tap/client/api'), require('@iotize/tap/client/impl'), require('rxjs'), require('@iotize/common/debug'), require('@iotize/common/array'), require('@iotize/common/byte-converter'), require('rxjs/operators'), require('@iotize/common/error')) :
    typeof define === 'function' && define.amd ? define('@iotize/tap', ['exports', '@iotize/tap/client/api', '@iotize/tap/client/impl', 'rxjs', '@iotize/common/debug', '@iotize/common/array', '@iotize/common/byte-converter', 'rxjs/operators', '@iotize/common/error'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.iotize = global.iotize || {}, global.iotize.tap = {}), global.iotize.tap.client.api, global.iotize.tap.client.impl, global.rxjs, global.debug$1, global.array, global.byteConverter, global.rxjs.operators, global.error));
})(this, (function (exports, api, impl, rxjs, debug$1, array, byteConverter, operators, error) { 'use strict';

    exports.PathParameter = /** @class */ (function () {
        function PathParameter() {
        }
        PathParameter.fillParam = function (path, key, value) {
            var map = {};
            map[key] = value;
            return PathParameter.fillParams(path, map);
        };
        /**
         * Same as fillParams but will throw an error if some parameters has not been replaced
         */
        PathParameter.fillAllParams = function (path, pathParameters) {
            path = PathParameter.fillParams(path, pathParameters);
            var remainingArgs = PathParameter.extractParams(path);
            if (remainingArgs.length > 0) {
                throw new Error("Missing path parameter " + remainingArgs.join(', ') + " (path: " + path + ")");
            }
            return path;
        };
        PathParameter.fillParams = function (path, mapping) {
            for (var key in mapping) {
                var match = '{' + key + '}';
                if (path.indexOf(match) >= 0) {
                    path = path.replace(match, mapping[key].toString());
                }
                else {
                    throw new Error('Parameter ' + key + ' does not exist in path: ' + path);
                }
            }
            return path;
        };
        /**
         *
         * @param path
         * @returns names of path parameters
         */
        PathParameter.extractParams = function (path) {
            var found = [], rxp = PathParameter.PARAMETER_REGEX, curMatch;
            while ((curMatch = rxp.exec(path))) {
                found.push(curMatch[1]);
            }
            return found;
        };
        PathParameter.hasParams = function (path) {
            return PathParameter.extractParams(path).length > 0;
        };
        return PathParameter;
    }());
    (function (PathParameter) {
        PathParameter.PARAMETER_REGEX = /{([^}]+)}/g;
    })(exports.PathParameter || (exports.PathParameter = {}));

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */
    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 (Object.prototype.hasOwnProperty.call(b, p))
                    d[p] = b[p]; };
        return extendStatics(d, b);
    };
    function __extends(d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }
    var __assign = function () {
        __assign = Object.assign || function __assign(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s)
                    if (Object.prototype.hasOwnProperty.call(s, p))
                        t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
        var t = {};
        for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
                t[p] = s[p];
        if (s != null && typeof Object.getOwnPropertySymbols === "function")
            for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                    t[p[i]] = s[p[i]];
            }
        return t;
    }
    function __decorate(decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
            r = Reflect.decorate(decorators, target, key, desc);
        else
            for (var i = decorators.length - 1; i >= 0; i--)
                if (d = decorators[i])
                    r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    }
    function __param(paramIndex, decorator) {
        return function (target, key) { decorator(target, key, paramIndex); };
    }
    function __metadata(metadataKey, metadataValue) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
            return Reflect.metadata(metadataKey, metadataValue);
    }
    function __awaiter$3(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());
        });
    }
    function __generator(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 };
        }
    }
    var __createBinding = Object.create ? (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
    }) : (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        o[k2] = m[k];
    });
    function __exportStar(m, o) {
        for (var p in m)
            if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
                __createBinding(o, m, p);
    }
    function __values(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m)
            return m.call(o);
        if (o && typeof o.length === "number")
            return {
                next: function () {
                    if (o && i >= o.length)
                        o = void 0;
                    return { value: o && o[i++], done: !o };
                }
            };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    }
    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m)
            return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
                ar.push(r.value);
        }
        catch (error) {
            e = { error: error };
        }
        finally {
            try {
                if (r && !r.done && (m = i["return"]))
                    m.call(i);
            }
            finally {
                if (e)
                    throw e.error;
            }
        }
        return ar;
    }
    /** @deprecated */
    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }
    /** @deprecated */
    function __spreadArrays() {
        for (var s = 0, i = 0, il = arguments.length; i < il; i++)
            s += arguments[i].length;
        for (var r = Array(s), k = 0, i = 0; i < il; i++)
            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                r[k] = a[j];
        return r;
    }
    function __spreadArray(to, from, pack) {
        if (pack || arguments.length === 2)
            for (var i = 0, l = from.length, ar; i < l; i++) {
                if (ar || !(i in from)) {
                    if (!ar)
                        ar = Array.prototype.slice.call(from, 0, i);
                    ar[i] = from[i];
                }
            }
        return to.concat(ar || Array.prototype.slice.call(from));
    }
    function __await(v) {
        return this instanceof __await ? (this.v = v, this) : new __await(v);
    }
    function __asyncGenerator(thisArg, _arguments, generator) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var g = generator.apply(thisArg, _arguments || []), i, q = [];
        return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
        function verb(n) { if (g[n])
            i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
        function resume(n, v) { try {
            step(g[n](v));
        }
        catch (e) {
            settle(q[0][3], e);
        } }
        function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
        function fulfill(value) { resume("next", value); }
        function reject(value) { resume("throw", value); }
        function settle(f, v) { if (f(v), q.shift(), q.length)
            resume(q[0][0], q[0][1]); }
    }
    function __asyncDelegator(o) {
        var i, p;
        return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
        function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
    }
    function __asyncValues(o) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var m = o[Symbol.asyncIterator], i;
        return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
        function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
        function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
    }
    function __makeTemplateObject(cooked, raw) {
        if (Object.defineProperty) {
            Object.defineProperty(cooked, "raw", { value: raw });
        }
        else {
            cooked.raw = raw;
        }
        return cooked;
    }
    ;
    var __setModuleDefault = Object.create ? (function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v });
    }) : function (o, v) {
        o["default"] = v;
    };
    function __importStar(mod) {
        if (mod && mod.__esModule)
            return mod;
        var result = {};
        if (mod != null)
            for (var k in mod)
                if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
                    __createBinding(result, mod, k);
        __setModuleDefault(result, mod);
        return result;
    }
    function __importDefault(mod) {
        return (mod && mod.__esModule) ? mod : { default: mod };
    }
    function __classPrivateFieldGet(receiver, state, kind, f) {
        if (kind === "a" && !f)
            throw new TypeError("Private accessor was defined without a getter");
        if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
            throw new TypeError("Cannot read private member from an object whose class did not declare it");
        return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
    }
    function __classPrivateFieldSet(receiver, state, value, kind, f) {
        if (kind === "m")
            throw new TypeError("Private method is not writable");
        if (kind === "a" && !f)
            throw new TypeError("Private accessor was defined without a setter");
        if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
            throw new TypeError("Cannot write private member to an object whose class did not declare it");
        return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
    }

    var prefix = '@iotize/tap';
    var lazyDebug = debug$1.createLazyDebugger(prefix);
    var debug = debug$1.createDebugger(prefix);

    exports.TapError = /** @class */ (function (_super) {
        __extends(TapError, _super);
        function TapError(code, message, cause) {
            var _this = _super.call(this, message, code) || this;
            _this.cause = cause;
            return _this;
        }
        TapError.cannotStartScram = function (err) {
            return new TapError(TapError.Code.CannotStartScram, "Cannot start encrypted session, initialization failed. Cause: " + err.message, err);
        };
        TapError.notImplementedYet = function (msg) {
            throw new TapError(TapError.Code.NotImplemented, msg);
        };
        TapError.initializationVectorNotSupported = function (err) {
            return new TapError(TapError.Code.InitializationVectorNotSupported, "Initialization vector for SCRAM is not implemented with your current firmware version. You cannot use this feature.", err);
        };
        TapError.executeRequestError = function (request, err) {
            return new TapError(TapError.Code.ExecuteRequestError, "Tap request " + api.TapRequestFrame.MethodType[request.method] + " " + (request.pathAlias || request.path) + " failed. " + err.message, err);
        };
        TapError.reponseStatusError = function (response, call) {
            return new TapResponseStatusError(response, call);
        };
        TapError.invalidServiceCallConfiguration = function (msg) {
            return new TapError(TapError.Code.InvalidServiceCallConfiguration, msg);
        };
        TapError.appendChunkError = function (cause, chunk, progress) {
            return new AppendChunkError(cause, chunk, progress);
        };
        TapError.nfcPairingError = function (msg, cause) {
            return new TapError(TapError.Code.NfcPairingError, "NFC pairing failed. " + msg, cause);
        };
        return TapError;
    }(error.CodeError));
    (function (TapError) {
        var Code;
        (function (Code) {
            Code["CannotStartScram"] = "TapErrorCannotStartScram";
            Code["NotImplemented"] = "TapErrorNotImplemented";
            Code["InitializationVectorNotSupported"] = "TapErrorInitializationVectorNotSupported";
            Code["AppendChunkError"] = "AppendChunkError";
            Code["ResponseStatusError"] = "TapErrorTapResponseStatusError";
            Code["InvalidServiceCallConfiguration"] = "TapErrorInvalidServiceCallConfiguration";
            Code["ExecuteRequestError"] = "TapErrorTapExecuteRequestError";
            Code["NfcPairingError"] = "TapErrorNfcPairingError";
            Code["ScramNotStartedYet"] = "TapErrorScramNotStartedYet";
            Code["InvalidScramKey"] = "TapErrorInvalidScramKey";
        })(Code = TapError.Code || (TapError.Code = {}));
    })(exports.TapError || (exports.TapError = {}));
    var TapResponseStatusError = /** @class */ (function (_super) {
        __extends(TapResponseStatusError, _super);
        function TapResponseStatusError(response, call) {
            var _this = _super.call(this, exports.TapError.Code.ResponseStatusError, "Tap request " + (call
                ? serviceCallToString(call) + " "
                : response.request
                    ? impl.TapRequestHelper.toString(response.request) + ' '
                    : '') + "failed. " + impl.tapResponseStatusToString(response.status) + " (status code 0x" + response.status.toString(16) + ")") || this;
            _this.response = response;
            return _this;
        }
        return TapResponseStatusError;
    }(exports.TapError));
    var AppendChunkError = /** @class */ (function (_super) {
        __extends(AppendChunkError, _super);
        function AppendChunkError(cause, chunk, progress) {
            var _this = _super.call(this, exports.TapError.Code.AppendChunkError, "Appending data chunk n\u00B0" + progress.loaded + "/" + progress.total + " failed with error: " + cause.message, cause) || this;
            _this.chunk = chunk;
            _this.progress = progress;
            return _this;
        }
        return AppendChunkError;
    }(exports.TapError));

    var TapResponse = /** @class */ (function () {
        function TapResponse(_tapResponse, request, bodyDecoder) {
            this._tapResponse = _tapResponse;
            this.request = request;
            this.bodyDecoder = bodyDecoder;
        }
        TapResponse.SUCCESS = function (data) {
            return TapResponse.create(api.ResultCode.OK, data);
        };
        TapResponse.ERROR = function (errorCode) {
            errorCode = errorCode || api.ResultCode.BAD_REQUEST;
            return TapResponse.create(errorCode);
        };
        TapResponse.create = function (codeRet, data) {
            return new TapResponse(impl.TapResponseFrameBuilder.create(codeRet, data));
        };
        Object.defineProperty(TapResponse.prototype, "data", {
            get: function () {
                return this._tapResponse.data;
            },
            enumerable: false,
            configurable: true
        });
        TapResponse.prototype.body = function (decoder) {
            this.successful();
            if (decoder) {
                return decoder.decode(this.rawBody());
            }
            else if (this._bodyCache === undefined) {
                if (this.bodyDecoder) {
                    this._bodyCache = this.bodyDecoder.decode(this.rawBody());
                }
                else {
                    this._bodyCache = this.rawBody();
                }
            }
            // In this case we now that T = DataType
            return this._bodyCache;
        };
        TapResponse.prototype.rawBody = function () {
            if (this.data) {
                return this.data;
            }
            else {
                return new Uint8Array(0);
            }
        };
        TapResponse.prototype.setBodyDecoder = function (decoder) {
            this.bodyDecoder = decoder;
            return this;
        };
        TapResponse.prototype.hasBody = function () {
            return this.rawBody() != null;
        };
        TapResponse.prototype.codeRet = function () {
            return this.status;
        };
        Object.defineProperty(TapResponse.prototype, "status", {
            get: function () {
                return this._tapResponse.status;
            },
            enumerable: false,
            configurable: true
        });
        TapResponse.prototype.toString = function () {
            return "ResponseMessage[codeRet=\"" + this.status + "\";data=\"" + (this.hasBody() ? byteConverter.bufferToHexString(this.rawBody()) : 'NO DATA') + "\";decoder=" + (this.bodyDecoder ? this.bodyDecoder.constructor.name : 'NONE') + "]";
        };
        TapResponse.prototype.toBytes = function () {
            return this.data;
        };
        TapResponse.prototype.setBody = function (body) {
            this._bodyCache = body;
        };
        TapResponse.prototype.isSuccessful = function () {
            return (this.status & 0x80) === 0;
        };
        TapResponse.prototype.setError = function (err) {
            return (this.error = err);
        };
        TapResponse.prototype.successful = function () {
            if (!this.isSuccessful()) {
                if (this.error) {
                    throw this.error;
                }
                else {
                    throw exports.TapError.reponseStatusError(this);
                }
            }
        };
        TapResponse.prototype.setRequest = function (request) {
            this.request = request;
        };
        return TapResponse;
    }());

    var __awaiter$2 = (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());
        });
    };
    function serviceCallToString(call, options) {
        function printObject(obj) {
            if (obj instanceof Uint8Array) {
                return '0x' + byteConverter.bufferToHexString(obj);
            }
            else if (typeof obj === 'object') {
                return ('{' +
                    Object.keys(obj)
                        .map(function (key) { return "\"" + key + "\":" + printObject(obj[key]); })
                        .join(',') +
                    '}');
            }
            else {
                return JSON.stringify(obj);
            }
        }
        var lwm2mPath = ServiceCallRunner.resolvePathParameters(call);
        var pathAlias = call.pathAlias
            ? exports.PathParameter.fillAllParams(call.pathAlias, call.pathParameters || {})
            : undefined;
        var result = api.TapRequestFrame.MethodType[call.method] + " " + (pathAlias || lwm2mPath);
        if (call.pathAlias) {
            result += " (" + lwm2mPath + ")";
        }
        if (!(options === null || options === void 0 ? void 0 : options.skipBody) && call.body !== undefined) {
            result += ' ' + printObject(call.body);
        }
        return result;
    }
    var ServiceCallRunner = /** @class */ (function () {
        function ServiceCallRunner(client, options) {
            if (options === void 0) { options = {
                chunkSize: 220,
            }; }
            this.client = client;
            this.options = options;
        }
        ServiceCallRunner.prototype.get = function (path, body) {
            return this.execute({
                method: api.TapRequestFrame.MethodType.GET,
                path: path,
                body: body,
            });
        };
        ServiceCallRunner.prototype.put = function (path, body) {
            return this.execute({
                method: api.TapRequestFrame.MethodType.PUT,
                path: path,
                body: body,
            });
        };
        ServiceCallRunner.prototype.post = function (path, body) {
            return this.execute({
                method: api.TapRequestFrame.MethodType.POST,
                path: path,
                body: body,
            });
        };
        ServiceCallRunner.prototype.prepare = function (call) {
            var _this = this;
            return rxjs.defer(function () { return __awaiter$2(_this, void 0, void 0, function () {
                var tapRequestFrame, tapResponseFrame, response, responseBodyDecoder, err_1;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            tapRequestFrame = ServiceCallRunner.toTapRequest(call);
                            _a.label = 1;
                        case 1:
                            _a.trys.push([1, 3, , 4]);
                            return [4 /*yield*/, this.client
                                    .request(tapRequestFrame)
                                    .toPromise()];
                        case 2:
                            tapResponseFrame = _a.sent();
                            if (!tapResponseFrame) {
                                throw new Error("No Tap response");
                            }
                            response = new TapResponse(tapResponseFrame, tapRequestFrame);
                            responseBodyDecoder = ServiceCallRunner.resolveResponseBodyDecoder(call);
                            if (responseBodyDecoder) {
                                response.setBodyDecoder({
                                    decode: responseBodyDecoder,
                                });
                            }
                            if (!response.isSuccessful()) {
                                response.setError(exports.TapError.reponseStatusError(response, call));
                            }
                            return [2 /*return*/, response];
                        case 3:
                            err_1 = _a.sent();
                            if (!(err_1 instanceof exports.TapError)) {
                                throw exports.TapError.executeRequestError(call, err_1);
                            }
                            throw err_1;
                        case 4: return [2 /*return*/];
                    }
                });
            }); });
            // return response$.pipe(
            //     tap(
            //         response => {
            //             debug(this.constructor.name, ...debugArgs, '=>', response.toString());
            //         },
            //         err => {
            //             debug(this.constructor.name, ...debugArgs, ` => ${err.message}`);
            //         }
            //     )
            // );
        };
        ServiceCallRunner.prototype.execute = function (call) {
            return this.prepare(call).pipe(operators.first()).toPromise();
        };
        ServiceCallRunner.prototype.createAppendCalls = function (call, chunkSize) {
            if (chunkSize === void 0) { chunkSize = this.options.chunkSize; }
            var chunks = array.chunkArray(Array.from(call.body || new Uint8Array()), chunkSize).map(function (chunk, index) {
                return Object.assign(Object.assign({}, call), { body: Uint8Array.from(chunk) });
            });
            return chunks;
        };
        ServiceCallRunner.prototype.prepareAppendCall = function (call, chunkSize) {
            var _this = this;
            if (chunkSize === void 0) { chunkSize = this.options.chunkSize; }
            return new rxjs.Observable(function (emitter) {
                var isCancelled = false;
                (function () { return __awaiter$2(_this, void 0, void 0, function () {
                    var calls, index, byteOffset, calls_1, calls_1_1, call_1, chunk, progress, response, e_1_1, err_2;
                    var e_1, _a;
                    return __generator(this, function (_b) {
                        switch (_b.label) {
                            case 0:
                                _b.trys.push([0, 9, , 10]);
                                calls = this.createAppendCalls(call, chunkSize);
                                index = 0;
                                byteOffset = 0;
                                _b.label = 1;
                            case 1:
                                _b.trys.push([1, 6, 7, 8]);
                                calls_1 = __values(calls), calls_1_1 = calls_1.next();
                                _b.label = 2;
                            case 2:
                                if (!!calls_1_1.done) return [3 /*break*/, 5];
                                call_1 = calls_1_1.value;
                                if (isCancelled) {
                                    return [2 /*return*/];
                                }
                                chunk = call_1.body;
                                progress = {
                                    total: chunk.length,
                                    loaded: index + 1,
                                    byteOffset: byteOffset,
                                };
                                emitter.next(progress);
                                return [4 /*yield*/, this.execute({
                                        method: call_1.method || api.TapRequestFrame.MethodType.PUT,
                                        path: call_1.path,
                                        body: chunk,
                                    })];
                            case 3:
                                response = _b.sent();
                                try {
                                    response.successful();
                                }
                                catch (err) {
                                    throw exports.TapError.appendChunkError(err, chunk, progress);
                                }
                                byteOffset += chunk.length;
                                index++;
                                _b.label = 4;
                            case 4:
                                calls_1_1 = calls_1.next();
                                return [3 /*break*/, 2];
                            case 5: return [3 /*break*/, 8];
                            case 6:
                                e_1_1 = _b.sent();
                                e_1 = { error: e_1_1 };
                                return [3 /*break*/, 8];
                            case 7:
                                try {
                                    if (calls_1_1 && !calls_1_1.done && (_a = calls_1.return)) _a.call(calls_1);
                                }
                                finally { if (e_1) throw e_1.error; }
                                return [7 /*endfinally*/];
                            case 8:
                                emitter.complete();
                                return [3 /*break*/, 10];
                            case 9:
                                err_2 = _b.sent();
                                emitter.error(err_2);
                                return [2 /*return*/];
                            case 10: return [2 /*return*/];
                        }
                    });
                }); })();
                return function () {
                    // TODO throw error on cancel
                    isCancelled = true;
                };
            });
        };
        ServiceCallRunner.toTapRequest = function (call) {
            var path = ServiceCallRunner.resolvePathParameters(call);
            var body = ServiceCallRunner.encodeBody(call);
            return impl.TapRequestFrameBuilder.create(call.method, path, body);
        };
        ServiceCallRunner.resolveResponseBodyDecoder = function (call) {
            if (call.responseBodyDecoder) {
                return toDecoderFunction(call.responseBodyDecoder);
            }
            return undefined;
        };
        ServiceCallRunner.resolvePathParameters = function (info) {
            return exports.PathParameter.fillAllParams(info.path, info.pathParameters || {});
        };
        /**
         * Encode body according to options and configuration
         */
        ServiceCallRunner.encodeBody = function (options) {
            if (options.body === undefined) {
                return undefined;
            }
            var encoded = options.bodyEncoder
                ? toEncoderFunction(options.bodyEncoder)(options.body)
                : options.body;
            if (encoded !== undefined && !(encoded instanceof Uint8Array)) {
                throw exports.TapError.invalidServiceCallConfiguration("Request body encoder is required for call to " + serviceCallToString(options));
            }
            return encoded;
        };
        return ServiceCallRunner;
    }());
    function toEncoderFunction(classOrFunction) {
        return typeof classOrFunction === 'function'
            ? classOrFunction
            : classOrFunction.encode.bind(classOrFunction);
    }
    function toDecoderFunction(classOrFunction) {
        return typeof classOrFunction === 'function'
            ? classOrFunction
            : classOrFunction.decode.bind(classOrFunction);
    }

    var AbstractService = /** @class */ (function () {
        function AbstractService(serviceCallRunner) {
            this.serviceCallRunner = serviceCallRunner;
        }
        return AbstractService;
    }());

    /**
     * This class will be augmented when importing specific service
     * For example:
     * ```typescript
     * const container: ServiceContainer;
     * expect(container.interface).to.be.undefined;
     * import '@iotize/tap/service/interface';
     * expect(container.interface).to.be.not.undefined;
     *
     * ```
     */
    var ServiceContainer = /** @class */ (function () {
        function ServiceContainer(serviceCallRunner) {
            this.serviceCallRunner = serviceCallRunner;
        }
        /**
         * List loaded services
         */
        ServiceContainer.prototype.services = function () {
            return Object.values(this.servicesMap());
        };
        ServiceContainer.prototype.servicesMap = function () {
            var services = {};
            for (var key in this) {
                var hasDescriptor = Object.getOwnPropertyDescriptor(ServiceContainer.prototype, key);
                var value = this[key];
                if (hasDescriptor === null || hasDescriptor === void 0 ? void 0 : hasDescriptor.enumerable) {
                    if (value instanceof AbstractService) {
                        services[key] = value;
                    }
                }
            }
            return services;
        };
        /**
         * List all loaded resources
         */
        ServiceContainer.prototype.resources = function () {
            return this.services().reduce(function (prev, service) {
                prev.push.apply(prev, __spreadArray([], __read(Object.values(service.resources))));
                return prev;
            }, []);
        };
        return ServiceContainer;
    }());
    function extendServiceContainer(attrName, serviceConstructor) {
        var hiddenAttrName = "__" + attrName + "__";
        Object.defineProperty(ServiceContainer.prototype, hiddenAttrName, {
            enumerable: false,
            configurable: true,
            writable: true,
            value: undefined,
        });
        return Object.defineProperty(ServiceContainer.prototype, attrName, {
            get: function () {
                var that = this;
                if (!that[hiddenAttrName]) {
                    that[hiddenAttrName] = new serviceConstructor(this.serviceCallRunner);
                }
                return that[hiddenAttrName];
            },
            enumerable: true,
            configurable: true,
        });
    }

    var NFC_PAIRING_COMMAND = Uint8Array.from([
        0x00,
        0xa4,
        0x04,
        0x00,
        0x07,
        // DATA
        0xf0,
        0x02,
        0x4c,
        0x77,
        0x4d,
        0x32,
        0x4d,
        // --
        0x90,
        0x00, // SW2
    ]);
    var DEFAULT_TAP_MAX_FRAME_SIZE = 256 - 6; // Lc = u8 legnth - 5 header bytes  - 1 byte "Le"

    var __awaiter$1 = (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 TAG = 'Device';
    /**
     *
     */
    var Tap = /** @class */ (function () {
        function Tap(client) {
            this._events = new rxjs.Subject();
            this._client = client;
            this._lwm2m = new ServiceCallRunner(this.client);
            this.service = new ServiceContainer(this._lwm2m);
            // 'service', (context) => new ServiceContainer(context.tap.lwm2m)
            // this._scramInterceptor = new ScramInterceptor(
            //     this._services.scram,
            //     this.apiConfig
            // );
            // this._client.addInterceptor(this._scramInterceptor);
            // this._initCache();
            // this._converterProvider = new ConverterProvider(PathToTypeMap, DefaultConverterMap);
        }
        Object.defineProperty(Tap.prototype, "events", {
            get: function () {
                return this._events.asObservable();
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Tap.prototype, "client", {
            get: function () {
                return this._client;
            },
            set: function (client) {
                this._client = client;
                this._lwm2m.client = client;
                // this._services.client = client;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(Tap.prototype, "lwm2m", {
            get: function () {
                return this._lwm2m;
            },
            enumerable: false,
            configurable: true
        });
        Tap.prototype.notifyEvent = function (event) {
            this._events.next(event);
        };
        Tap.create = function () {
            return new Tap(impl.TapClient.create());
        };
        Tap.fromProtocol = function (protocol) {
            var client = impl.TapClient.create();
            client.addComProtocol(protocol);
            return new Tap(client);
        };
        Object.defineProperty(Tap.prototype, "protocol", {
            get: function () {
                return this.client.getCurrentProtocol();
            },
            enumerable: false,
            configurable: true
        });
        /**
         * Connect with the given communication protocol
         * TODO what if there is already a connected communication protocol
         * @param protocol
         */
        Tap.prototype.connect = function (protocol) {
            debug(TAG, 'connecting...');
            // this._clearCache();
            if (protocol) {
                this.client.addComProtocol(protocol, 'default');
            }
            return this._client.connect().toPromise();
        };
        /**
         * Disconnect device
         */
        Tap.prototype.disconnect = function () {
            debug(TAG, 'disconnecting...');
            // if (options.clearCache) {
            //     this.clearCache();
            // }
            // if (options.clearSession) {
            //     this.clearSession();
            // }
            return this._client.disconnect().toPromise();
        };
        Tap.prototype.isConnected = function () {
            if (!this._client) {
                return false;
            }
            return this._client.isConnected();
        };
        /**
         * Configure current tap instance thanks to a TapConfigurator
         * @param configurator
         */
        Tap.prototype.configure = function (configurator) {
            return configurator.configure(this).toPromise();
        };
        /**
         *
         * @param protocol
         */
        Tap.prototype.useComProtocol = function (protocol) {
            this.client.useComProtocol(protocol);
            return this;
        };
        /**
         * Send an NFC pairing request
         */
        Tap.prototype.nfcPairing = function () {
            return __awaiter$1(this, void 0, void 0, function () {
                var comProtocol, response, statusCode;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4 /*yield*/, this.client.getCurrentProtocol()];
                        case 1:
                            comProtocol = _a.sent();
                            return [4 /*yield*/, comProtocol.send(NFC_PAIRING_COMMAND).toPromise()];
                        case 2:
                            response = _a.sent();
                            if (!response || response.length !== 2) {
                                throw exports.TapError.nfcPairingError("Tap responded with a frame size of " + ((response === null || response === void 0 ? void 0 : response.length) || 0) + " byte(s) but expecting 2 bytes.");
                            }
                            statusCode = impl.NumberConverter.uint16().decode(response);
                            if (statusCode !== api.ApduResponse.Status.OK) {
                                throw exports.TapError.nfcPairingError("Tap responded with an invalid APDU response status 0x" + statusCode.toString(16) + ".");
                            }
                            return [2 /*return*/, response];
                    }
                });
            });
        };
        return Tap;
    }());
    Tap.TAG = 'Tap';

    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());
        });
    };
    /**
     * If response status code is NOT_IMPLEMENTED or NOT_FOUND it will returns the default value
     * @param responsePromise
     * @param defaultValue
     */
    function defaultValueIfTapRequetNotImplemented(responsePromise, defaultValue) {
        return __awaiter(this, void 0, void 0, function () {
            var response;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, responsePromise];
                    case 1:
                        response = _a.sent();
                        if (!response.isSuccessful()) {
                            if (response.status === api.ResultCode.NOT_IMPLEMENTED ||
                                response.status === api.ResultCode.NOT_FOUND) {
                                return [2 /*return*/, defaultValue];
                            }
                        }
                        return [2 /*return*/, response.body()];
                }
            });
        });
    }
    /**
     * Utility function add a new getter to the Tap prototype
     */
    function defineTapPropertyExtension(propName, factory) {
        Object.defineProperty(Tap.prototype, propName, {
            get: function () {
                var that = this;
                var hiddentPropName = "__" + propName + "__";
                if (!that[hiddentPropName]) {
                    that[hiddentPropName] = factory({
                        tap: this,
                    });
                }
                return that[hiddentPropName];
            },
            enumerable: false,
            configurable: true,
        });
    }

    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.HostProtocol = void 0;
    (function (HostProtocol) {
        HostProtocol[HostProtocol["NFC"] = 1] = "NFC";
        HostProtocol[HostProtocol["BLUETOOTH"] = 2] = "BLUETOOTH";
        HostProtocol[HostProtocol["GSM"] = 4] = "GSM";
        HostProtocol[HostProtocol["USB_RLINK"] = 8] = "USB_RLINK";
        HostProtocol[HostProtocol["USB_CMISIS_DAP"] = 16] = "USB_CMISIS_DAP";
        HostProtocol[HostProtocol["WIFI"] = 32] = "WIFI";
        HostProtocol[HostProtocol["BLE"] = 64] = "BLE";
        HostProtocol[HostProtocol["LORA"] = 128] = "LORA";
        HostProtocol[HostProtocol["UART"] = 256] = "UART";
        HostProtocol[HostProtocol["MQTT"] = 512] = "MQTT";
        HostProtocol[HostProtocol["WEBSOCKET"] = 1024] = "WEBSOCKET";
        HostProtocol[HostProtocol["SLAVE_SERVER"] = 2048] = "SLAVE_SERVER";
    })(exports.HostProtocol || (exports.HostProtocol = {}));
    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.TargetProtocol = void 0;
    (function (TargetProtocol) {
        TargetProtocol[TargetProtocol["SWD"] = 0] = "SWD";
        TargetProtocol[TargetProtocol["S3P"] = 1] = "S3P";
        TargetProtocol[TargetProtocol["JTAG"] = 2] = "JTAG";
        TargetProtocol[TargetProtocol["MODBUS"] = 3] = "MODBUS";
        TargetProtocol[TargetProtocol["DIRECT_IO"] = 4] = "DIRECT_IO";
        TargetProtocol[TargetProtocol["SERIAL"] = 6] = "SERIAL";
        TargetProtocol[TargetProtocol["CUSTOM"] = 7] = "CUSTOM";
        TargetProtocol[TargetProtocol["CAN"] = 8] = "CAN";
        TargetProtocol[TargetProtocol["MODBUS_TCP"] = 9] = "MODBUS_TCP";
        TargetProtocol[TargetProtocol["NONE"] = 255] = "NONE";
    })(exports.TargetProtocol || (exports.TargetProtocol = {}));
    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.VariableFormat = void 0;
    (function (VariableFormat) {
        VariableFormat[VariableFormat["_1_BIT"] = 0] = "_1_BIT";
        VariableFormat[VariableFormat["_8_BITS"] = 1] = "_8_BITS";
        VariableFormat[VariableFormat["_16_BITS"] = 2] = "_16_BITS";
        VariableFormat[VariableFormat["_32_BITS"] = 3] = "_32_BITS";
    })(exports.VariableFormat || (exports.VariableFormat = {}));
    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.AppPathType = void 0;
    (function (AppPathType) {
        AppPathType["PRIMER_CLOUD_WEB_APP_URL"] = "$1/";
        AppPathType["URL"] = "$2/";
        AppPathType["ANDROID_APP_ID"] = "$4/";
        AppPathType["PRIMER_CLOUD_CONFIG_URL"] = "$5/";
        AppPathType["AAR_2"] = "$6/";
    })(exports.AppPathType || (exports.AppPathType = {}));
    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.SpecialFeature = void 0;
    (function (SpecialFeature) {
        SpecialFeature[SpecialFeature["SWD_DIRECT_ACCESS"] = 100] = "SWD_DIRECT_ACCESS";
        SpecialFeature[SpecialFeature["SERIAL_ACCESS"] = 101] = "SERIAL_ACCESS";
        SpecialFeature[SpecialFeature["MODBUS_DIRECT_ACCESS"] = 102] = "MODBUS_DIRECT_ACCESS";
        SpecialFeature[SpecialFeature["TAPNPASS_CONTROL_ACCESS"] = 103] = "TAPNPASS_CONTROL_ACCESS";
        SpecialFeature[SpecialFeature["SP_CODEEXEC_ACCESS"] = 104] = "SP_CODEEXEC_ACCESS";
        SpecialFeature[SpecialFeature["MQTT_IDS_ACCESS"] = 105] = "MQTT_IDS_ACCESS";
        SpecialFeature[SpecialFeature["VARIABLE_CONFIG_ACCESS"] = 106] = "VARIABLE_CONFIG_ACCESS";
        SpecialFeature[SpecialFeature["FILE_SYSTEM_ACCESS"] = 107] = "FILE_SYSTEM_ACCESS";
    })(exports.SpecialFeature || (exports.SpecialFeature = {}));
    /* eslint-disable */
    /**
     * This file was automatically generated by json-schema-to-typescript.
     * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
     * and run json-schema-to-typescript to regenerate this file.
     */
    exports.CpuFrequencySpeed = void 0;
    (function (CpuFrequencySpeed) {
        CpuFrequencySpeed[CpuFrequencySpeed["NORMAL"] = 0] = "NORMAL";
        CpuFrequencySpeed[CpuFrequencySpeed["SLOW"] = 1] = "SLOW";
        CpuFrequencySpeed[CpuFrequencySpeed["FAST"] = 2] = "FAST";
    })(exports.CpuFrequencySpeed || (exports.CpuFrequencySpeed = {}));

    /**
     *   Generated file. Do not edit
     */
    impl.TapStreamReader.prototype.readTapVersion = function () {
        var model = {};
        model.major = this.readUnsigned(1);
        model.minor = this.readUnsigned(1);
        model.patch = this.readUnsigned(2);
        return model;
    };
    // TapStreamWriter.prototype.write(model: TapVersion) : TapStreamWriter{
    //     return this.writeTapVersion(model)
    // }
    impl.TapStreamWriter.prototype.writeTapVersion = function (model) {
        this.writeUnsigned(model.major !== undefined ? model.major : 0, 1);
        this.writeUnsigned(model.minor !== undefined ? model.minor : 0, 1);
        this.writeUnsigned(model.patch !== undefined ? model.patch : 0, 2);
        return this;
    };

    /**
     *   Generated file. Do not edit
     */
    var TapVersionConverter = /** @class */ (function () {
        function TapVersionConverter() {
        }
        TapVersionConverter.prototype.encode = function (model, stream) {
            if (stream === void 0) { stream = new impl.TapStreamWriter(); }
            stream.writeTapVersion(model);
            return stream.toBytes;
        };
        TapVersionConverter.prototype.decode = function (data) {
            var stream = data instanceof impl.TapStreamReader ? data : impl.TapStreamReader.create(data);
            return stream.readTapVersion();
        };
        return TapVersionConverter;
    }());

    /**
     * Generated bundle index. Do not edit.
     */

    exports.AbstractService = AbstractService;
    exports.DEFAULT_TAP_MAX_FRAME_SIZE = DEFAULT_TAP_MAX_FRAME_SIZE;
    exports.NFC_PAIRING_COMMAND = NFC_PAIRING_COMMAND;
    exports.ServiceCallRunner = ServiceCallRunner;
    exports.ServiceContainer = ServiceContainer;
    exports.Tap = Tap;
    exports.TapResponse = TapResponse;
    exports.TapResponseStatusError = TapResponseStatusError;
    exports.TapVersionConverter = TapVersionConverter;
    exports.defaultValueIfTapRequetNotImplemented = defaultValueIfTapRequetNotImplemented;
    exports.defineTapPropertyExtension = defineTapPropertyExtension;
    exports.extendServiceContainer = extendServiceContainer;
    exports.serviceCallToString = serviceCallToString;
    exports["ɵa"] = AppendChunkError;

    Object.defineProperty(exports, '__esModule', { value: true });

}));
//# sourceMappingURL=iotize-tap.umd.js.map
