"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 kaitai_stream_reader_1 = require("../../../core/kaitai/kaitai-stream-reader");
var kaitai_stream_writer_1 = require("../../../core/kaitai/kaitai-stream-writer");
var error_detection_1 = require("../../../core/error-detection");
function typedArrayToBuffer(array) {
    return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset);
}
exports.typedArrayToBuffer = typedArrayToBuffer;
var TapStreamReader = /** @class */ (function (_super) {
    __extends(TapStreamReader, _super);
    function TapStreamReader() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TapStreamReader.fromArray = function (array) {
        var buffer = typedArrayToBuffer(array);
        return new TapStreamReader(buffer);
    };
    TapStreamReader.create = function (packet) {
        return packet instanceof Uint8Array ? TapStreamReader.fromArray(packet) : packet;
    };
    TapStreamReader.prototype.readStr = function (n) {
        return String.fromCharCode.apply(null, this.readBytes(n));
    };
    TapStreamReader.prototype.readU2 = function () {
        return this._isBigEndian ? this.readU2be() : this.readU2le();
    };
    TapStreamReader.prototype.readU4 = function () {
        return this._isBigEndian ? this.readU4be() : this.readU4le();
    };
    TapStreamReader.prototype.readF4 = function () {
        return this._isBigEndian ? this.readF4be() : this.readF4le();
    };
    TapStreamReader.prototype.subStream = function (length) {
        return TapStreamReader.fromArray(this.readBytes(length));
    };
    return TapStreamReader;
}(kaitai_stream_reader_1.KaitaiStreamReader));
exports.TapStreamReader = TapStreamReader;
var TapStreamWriter = /** @class */ (function (_super) {
    __extends(TapStreamWriter, _super);
    function TapStreamWriter(lengthOrBuffer, byteOffset, isBigEndian) {
        if (lengthOrBuffer === void 0) { lengthOrBuffer = 512; }
        if (isBigEndian === void 0) { isBigEndian = true; }
        var _this = this;
        if (typeof lengthOrBuffer === "number") {
            lengthOrBuffer = new ArrayBuffer(lengthOrBuffer);
        }
        _this = _super.call(this, lengthOrBuffer, byteOffset, isBigEndian) || this;
        return _this;
    }
    TapStreamWriter.prototype.writeFunction = function (type, options, fieldValue, fieldSize) {
        switch (type) {
            case 'crc32':
                return this.addCRC(options);
            case 'padding':
                if (fieldValue) {
                    return this.writeBytes(fieldValue);
                }
                else {
                    if (typeof fieldSize == undefined) {
                        throw new Error("Padding function expect padding size as a second argument. Args: " + JSON.stringify(arguments));
                    }
                    return this.addPadding(fieldSize);
                }
            default:
                throw new Error("Invalid writer function type: " + type);
        }
    };
    TapStreamWriter.prototype.addPadding = function (padSize) {
        this.writeBytes(new Uint8Array(padSize));
        return this;
    };
    TapStreamWriter.prototype.addCRC = function (options) {
        var buffer = this.toBytes;
        if (options && options.offset) {
            buffer = buffer.slice(options.offset);
        }
        var crc = error_detection_1.CRC.fromBytes(buffer);
        this.writeU4(crc);
        return this;
    };
    TapStreamWriter.prototype.writeU4 = function (value) {
        this.writeU(value, 4);
        return this;
    };
    TapStreamWriter.prototype.writeU2 = function (value) {
        this.writeU(value, 2);
        return this;
    };
    TapStreamWriter.prototype.writeU1 = function (value) {
        this.writeU(value, 1);
        return this;
    };
    TapStreamWriter.prototype.writeF4 = function (value) {
        this.writeF(value, 4);
        return this;
    };
    TapStreamWriter.prototype.writeStr = function (value, length) {
        if (length === void 0) { length = value.length; }
        var i = 1;
        var stringWriteLength = Math.min(value.length, length);
        for (; i <= stringWriteLength; i++) {
            this.writeByte(value.charCodeAt(i - 1));
        }
        var remaining = length - stringWriteLength;
        if (remaining > 0) {
            this.writeBytes(new Uint8Array(remaining));
        }
        return this;
    };
    TapStreamWriter.prototype.writeByte = function (byte) {
        this._dataView.setInt8(this.pos, byte);
        this.pos++;
        return this;
    };
    TapStreamWriter.prototype.writeBitsInt = function (value, n) {
        this.writeB(value, n);
        return this;
    };
    return TapStreamWriter;
}(kaitai_stream_writer_1.KaitaiStreamWriter));
exports.TapStreamWriter = TapStreamWriter;
