var __values = (this && this.__values) || function(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.");
};
import { TLV } from '@iotize/common/tlv';
import { TLVConverter } from '../tlv-converter';
var TlvBundleConverter = /** @class */ (function () {
    function TlvBundleConverter(variables, tlvConverter) {
        if (variables === void 0) { variables = []; }
        if (tlvConverter === void 0) { tlvConverter = new TLVConverter(); }
        this.variables = variables;
        this.tlvConverter = tlvConverter;
        this.bundleId = 0;
    }
    TlvBundleConverter.prototype.decode = function (data, context) {
        if (data instanceof Uint8Array) {
            // Why this? 
            // const buffer = Buffer.from(data.buffer);
            data = this.tlvConverter.decode(data);
        }
        var result = this._convertFromTlvTree(data);
        if (!result || typeof result !== 'object' || result instanceof Uint8Array) {
            throw new Error("Invalid TLV frame"); // TODO proper error code
        }
        return result;
    };
    // {
    //     "header": {
    //         "id": 1,
    //         "type": 2,
    //         "len": 12
    //     },
    //     "children": [
    //         {
    //             "header": {
    //                 "id": 1,
    //                 "type": 3,
    //                 "len": 4
    //             },
    //             "payload": {
    //                 "type": "Buffer",
    //                 "data": [
    //                     64,
    //                     83,
    //                     127,
    //                     58
    //                 ]
    //             }
    //         },
    //         {
    //             "header": {
    //                 "id": 2,
    //                 "type": 3,
    //                 "len": 4
    //             },
    //             "payload": {
    //                 "type": "Buffer",
    //                 "data": [
    //                     65,
    //                     243,
    //                     141,
    //                     114
    //                 ]
    //             }
    //         }
    //     ]
    // }
    TlvBundleConverter.prototype.encode = function (data) {
        var _a;
        var tree = {
            header: {
                id: this.bundleId,
                len: 0,
                type: TLV.IdentifierType.MULTIPLE_RESOURCE
            },
            children: []
        };
        var totalLength = 0;
        var _loop_1 = function (key) {
            var value = data[key];
            var encodedValue = void 0;
            var meta = this_1.variables.find(function (m) { return m.name === key; });
            if (!meta) {
                meta = this_1.variables.find(function (m) { return m.id === parseInt(key, 10); });
            }
            // if (!meta) {
            //     // TODO use proper error with ErrorCode
            //     throw new Error(`Cannot find variable by identifier "${key}"`);
            // }
            if (meta === null || meta === void 0 ? void 0 : meta.converter) {
                encodedValue = (_a = meta.converter) === null || _a === void 0 ? void 0 : _a.encode(value);
            }
            else {
                if (!(value instanceof Uint8Array)) {
                    throw new Error("Add converter for variable with identifier \"" + key + "\"");
                }
                encodedValue = value;
            }
            if (!tree.children) {
                tree.children = [];
            }
            var id = (meta === null || meta === void 0 ? void 0 : meta.id) || parseInt(key, 10);
            if (isNaN(id)) {
                throw new Error("Cannot find variable by identifier \"" + key + "\"");
            }
            tree.children.push({
                header: {
                    id: id,
                    len: encodedValue.length,
                    type: TLV.IdentifierType.RESOURCE_VALUE
                },
                payload: encodedValue
            });
            totalLength += encodedValue.length + 2; // 2 for header length
        };
        var this_1 = this;
        for (var key in data) {
            _loop_1(key);
        }
        tree.header.len = totalLength;
        return this.tlvConverter.encode(tree);
    };
    /**
     * Converter tlv tree to variable name => value
     */
    TlvBundleConverter.prototype._convertFromTlvTree = function (tree, variableMeta) {
        var e_1, _a;
        // console.log('TLV =>', JSON.stringify(tree, null, 4));
        var result = {};
        // Recursive call to decode children
        if (tree.children) {
            result = {};
            var _loop_2 = function (child) {
                var e_2, _a;
                var variableMetas = this_2.variables.filter(function (v) { return v.id == child.header.id; });
                if (variableMetas.length == 0) {
                    variableMetas.push({
                        id: child.header.id
                    });
                }
                try {
                    for (var variableMetas_1 = (e_2 = void 0, __values(variableMetas)), variableMetas_1_1 = variableMetas_1.next(); !variableMetas_1_1.done; variableMetas_1_1 = variableMetas_1.next()) {
                        var variableMeta_1 = variableMetas_1_1.value;
                        var key = variableMeta_1 && variableMeta_1.name
                            ? variableMeta_1.name
                            : child.header.id.toString();
                        result[key] = this_2._convertFromTlvTree(child, variableMeta_1);
                    }
                }
                catch (e_2_1) { e_2 = { error: e_2_1 }; }
                finally {
                    try {
                        if (variableMetas_1_1 && !variableMetas_1_1.done && (_a = variableMetas_1.return)) _a.call(variableMetas_1);
                    }
                    finally { if (e_2) throw e_2.error; }
                }
            };
            var this_2 = this;
            try {
                for (var _b = __values(tree.children), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var child = _c.value;
                    _loop_2(child);
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_1) throw e_1.error; }
            }
        }
        // Decode current node
        else if (tree.payload) {
            var converter = variableMeta ? variableMeta.converter : undefined;
            if (converter) {
                result = converter.decode(tree.payload);
            }
            else {
                result = Uint8Array.from(tree.payload);
            }
        }
        return result;
    };
    return TlvBundleConverter;
}());
export { TlvBundleConverter };
//# sourceMappingURL=data:application/json;base64, 