/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */


const DeflaterHuffman = require("./DeflaterHuffman");

// Huffman tree used for inflation
class InflaterHuffmanTree {
    
    constructor(codeLengths) {
        this.tree = null;
        this.buildTree(codeLengths);
    }
    
    buildTree(codeLengths) {
        let blCount = new Int32Array(InflaterHuffmanTree.mAX_BITLEN + 1);
        let nextCode = new Int32Array(InflaterHuffmanTree.mAX_BITLEN + 1);
        for (let i = 0; i < codeLengths.length; i++) {
            let bits = codeLengths[i];
            if (bits > 0) 
                blCount[bits]++;
        }
        let code = 0;
        let treeSize = 512;
        for (let bits = 1; bits <= InflaterHuffmanTree.mAX_BITLEN; bits++) {
            nextCode[bits] = code;
            code += blCount[bits] << ((16 - bits));
            if (bits >= 10) {
                let start = nextCode[bits] & 0x1ff80;
                let end = code & 0x1ff80;
                treeSize += (((end - start)) >> ((16 - bits)));
            }
        }
        this.tree = new Int16Array(treeSize);
        let treePtr = 512;
        for (let bits = InflaterHuffmanTree.mAX_BITLEN; bits >= 10; bits--) {
            let end = code & 0x1ff80;
            code -= blCount[bits] << ((16 - bits));
            let start = code & 0x1ff80;
            for (let i = start; i < end; i += 1 << 7) {
                this.tree[DeflaterHuffman.bitReverse(i)] = (((-treePtr) << 4) | bits);
                treePtr += 1 << ((bits - 9));
            }
        }
        for (let i = 0; i < codeLengths.length; i++) {
            let bits = codeLengths[i];
            if (bits === 0) 
                continue;
            code = nextCode[bits];
            let revcode = DeflaterHuffman.bitReverse(code);
            if (bits <= 9) {
                do{
                    this.tree[revcode] = ((i << 4) | bits);
                    revcode += 1 << bits;
                } while (revcode < 512); 
            }
            else {
                let subTree = this.tree[revcode & 511];
                let treeLen = 1 << ((subTree & 15));
                subTree = -((subTree >> 4));
                do{
                    this.tree[subTree | ((revcode >> 9))] = ((i << 4) | bits);
                    revcode += 1 << bits;
                } while (revcode < treeLen); 
            }
            nextCode[bits] = code + (1 << ((16 - bits)));
        }
    }
    
    getSymbol(input) {
        let lookahead = 0;
        let symbol = 0;
        if ((((lookahead = input.peekBits(9)))) >= 0) {
            if ((((symbol = this.tree[lookahead]))) >= 0) {
                input.dropBits(symbol & 15);
                return symbol >> 4;
            }
            let subtree = -((symbol >> 4));
            let bitlen = symbol & 15;
            if ((((lookahead = input.peekBits(bitlen)))) >= 0) {
                symbol = this.tree[subtree | ((lookahead >> 9))];
                input.dropBits(symbol & 15);
                return symbol >> 4;
            }
            else {
                let bits = input.availableBits;
                lookahead = input.peekBits(bits);
                symbol = this.tree[subtree | ((lookahead >> 9))];
                if (((symbol & 15)) <= bits) {
                    input.dropBits(symbol & 15);
                    return symbol >> 4;
                }
                else 
                    return -1;
            }
        }
        else {
            let bits = input.availableBits;
            lookahead = input.peekBits(bits);
            symbol = this.tree[lookahead];
            if (symbol >= 0 && ((symbol & 15)) <= bits) {
                input.dropBits(symbol & 15);
                return symbol >> 4;
            }
            else 
                return -1;
        }
    }
    
    static static_constructor() {
        InflaterHuffmanTree.mAX_BITLEN = 15;
        InflaterHuffmanTree.DEF_LIT_LEN_TREE = null;
        InflaterHuffmanTree.DEF_DIST_TREE = null;
        try {
            let codeLengths = new Uint8Array(288);
            let i = 0;
            while (i < 144) {
                codeLengths[i++] = 8;
            }
            while (i < 256) {
                codeLengths[i++] = 9;
            }
            while (i < 280) {
                codeLengths[i++] = 7;
            }
            while (i < 288) {
                codeLengths[i++] = 8;
            }
            InflaterHuffmanTree.DEF_LIT_LEN_TREE = new InflaterHuffmanTree(codeLengths);
            codeLengths = new Uint8Array(32);
            i = 0;
            while (i < 32) {
                codeLengths[i++] = 5;
            }
            InflaterHuffmanTree.DEF_DIST_TREE = new InflaterHuffmanTree(codeLengths);
        } catch (ex) {
        }
    }
}


InflaterHuffmanTree.static_constructor();

module.exports = InflaterHuffmanTree