"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockMap = void 0;
const checksum_1 = require("./checksum");
const uint64_1 = require("./uint64");
const block_1 = require("./block");
/**
 * BlockMap (BLKX) data (aka Mish Data)
 */
class BlockMap {
    constructor() {
        /** Signature */
        this.signature = 0x00000000;
        /** Version number */
        this.version = 0x00000000;
        /** LBA of starting sector */
        this.sectorNumber = 0x0000000000000000;
        /** Number of sectors in this block range */
        this.sectorCount = 0x0000000000000000;
        /** Offset of data (within what?) */
        this.dataOffset = 0x0000000000000000;
        /** Buffers needed (?) */
        this.buffersNeeded = 0x00000000;
        /** Block descriptor number */
        this.blockDescriptorCount = 0x00000000;
        /** Reserved 1 */
        this.reserved1 = 0x00000000;
        /** Reserved 2 */
        this.reserved2 = 0x00000000;
        /** Reserved 3 */
        this.reserved3 = 0x00000000;
        /** Reserved 4 */
        this.reserved4 = 0x00000000;
        /** Reserved 5 */
        this.reserved5 = 0x00000000;
        /** Reserved 6 */
        this.reserved6 = 0x00000000;
        /** Checksum descriptor */
        this.checksum = new checksum_1.Checksum();
        /** Number of blocks in map */
        this.blockCount = 0x00000000;
        /** List of mapped blocks */
        this.blocks = [];
    }
    /** Parse BlockMap data from a buffer */
    static parse(buffer, offset = 0) {
        return new BlockMap().parse(buffer, offset);
    }
    /** Parse BlockMap data from a buffer */
    parse(buffer, offset = 0) {
        this.signature = buffer.readUInt32BE(offset + 0);
        if (this.signature !== BlockMap.SIGNATURE) {
            const expected = BlockMap.SIGNATURE.toString(16);
            const actual = this.signature.toString(16);
            throw new Error(`Invalid block map signature: Expected 0x${expected}, saw 0x${actual}`);
        }
        this.version = buffer.readUInt32BE(offset + 4);
        this.sectorNumber = (0, uint64_1.readBE)(buffer, offset + 8);
        this.sectorCount = (0, uint64_1.readBE)(buffer, offset + 16);
        this.dataOffset = (0, uint64_1.readBE)(buffer, offset + 24);
        this.buffersNeeded = buffer.readUInt32BE(offset + 32);
        this.blockDescriptorCount = buffer.readUInt32BE(offset + 36);
        this.reserved1 = buffer.readUInt32BE(offset + 40);
        this.reserved2 = buffer.readUInt32BE(offset + 44);
        this.reserved3 = buffer.readUInt32BE(offset + 48);
        this.reserved4 = buffer.readUInt32BE(offset + 52);
        this.reserved5 = buffer.readUInt32BE(offset + 56);
        this.reserved6 = buffer.readUInt32BE(offset + 60);
        this.checksum.parse(buffer, offset + 64);
        this.blockCount = buffer.readUInt32BE(offset + 200);
        this.blocks = [];
        for (let i = 0; i < this.blockCount; i++) {
            this.blocks.push(block_1.Block.parse(buffer, BlockMap.SIZE + i * block_1.Block.SIZE + offset));
        }
        return this;
    }
    /** Write BlockMap data to a buffer */
    write(buffer, offset = 0) {
        const length = BlockMap.SIZE + this.blocks.length * block_1.Block.SIZE;
        offset = offset || 0;
        buffer = buffer || Buffer.alloc(length + offset);
        // Update block count
        this.blockCount = this.blocks.length;
        buffer.writeUInt32BE(this.signature, offset + 0);
        buffer.writeUInt32BE(this.version, offset + 4);
        (0, uint64_1.writeBE)(buffer, this.sectorNumber, offset + 8);
        (0, uint64_1.writeBE)(buffer, this.sectorCount, offset + 16);
        (0, uint64_1.writeBE)(buffer, this.dataOffset, offset + 24);
        buffer.writeUInt32BE(this.buffersNeeded, offset + 32);
        buffer.writeUInt32BE(this.blockDescriptorCount, offset + 36);
        buffer.writeUInt32BE(this.reserved1, offset + 40);
        buffer.writeUInt32BE(this.reserved2, offset + 44);
        buffer.writeUInt32BE(this.reserved3, offset + 48);
        buffer.writeUInt32BE(this.reserved4, offset + 52);
        buffer.writeUInt32BE(this.reserved5, offset + 56);
        buffer.writeUInt32BE(this.reserved6, offset + 60);
        this.checksum.write(buffer, offset + 64);
        buffer.writeUInt32BE(this.blockCount, offset + 200);
        for (let i = 0; i < this.blockCount; i++) {
            this.blocks[i].write(buffer, BlockMap.SIZE + i * block_1.Block.SIZE + offset);
        }
        return buffer;
    }
}
exports.BlockMap = BlockMap;
/** Size of BlockMap structure in bytes (without Block entries) */
BlockMap.SIZE = 204;
/** BlockMap data signature */
BlockMap.SIGNATURE = 0x6d697368;
/** BLKX Version (latest known == 1) */
BlockMap.VERSION = 0x00000001;
BlockMap.Block = block_1.Block;
//# sourceMappingURL=blockmap.js.map