/*
 * 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 InflaterHuffmanTree = require("./InflaterHuffmanTree");

class InflaterDynHeader {
    
    constructor() {
        this.blLens = null;
        this.litdistLens = null;
        this.blTree = null;
        this.mode = 0;
        this.m_Lnum = 0;
        this.m_Dnum = 0;
        this.m_Blnum = 0;
        this.m_Num = 0;
        this.repSymbol = 0;
        this.lastLen = 0;
        this.ptr = 0;
    }
    
    decode(input) {
        for (; ; ) {
            switch (this.mode) { 
            case InflaterDynHeader.lNUM: {
                this.m_Lnum = input.peekBits(5);
                if (this.m_Lnum < 0) 
                    return false;
                this.m_Lnum += 257;
                input.dropBits(5);
                this.mode = InflaterDynHeader.dNUM;
                break;
            }
            case InflaterDynHeader.dNUM: {
                this.m_Dnum = input.peekBits(5);
                if (this.m_Dnum < 0) 
                    return false;
                this.m_Dnum++;
                input.dropBits(5);
                this.m_Num = this.m_Lnum + this.m_Dnum;
                this.litdistLens = new Uint8Array(this.m_Num);
                this.mode = InflaterDynHeader.bLNUM;
                break;
            }
            case InflaterDynHeader.bLNUM: {
                this.m_Blnum = input.peekBits(4);
                if (this.m_Blnum < 0) 
                    return false;
                this.m_Blnum += 4;
                input.dropBits(4);
                this.blLens = new Uint8Array(19);
                this.ptr = 0;
                this.mode = InflaterDynHeader.bLLENS;
                break;
            }
            case InflaterDynHeader.bLLENS: {
                while (this.ptr < this.m_Blnum) {
                    let len = input.peekBits(3);
                    if (len < 0) 
                        return false;
                    input.dropBits(3);
                    this.blLens[InflaterDynHeader.bL_ORDER[this.ptr]] = len;
                    this.ptr++;
                }
                this.blTree = new InflaterHuffmanTree(this.blLens);
                this.blLens = null;
                this.ptr = 0;
                this.mode = InflaterDynHeader.lENS;
                break;
            }
            case InflaterDynHeader.lENS: {{
                        let symbol = 0;
                        while ((((((symbol = this.blTree.getSymbol(input)))) & (~15))) === 0) {
                            this.litdistLens[this.ptr++] = (this.lastLen = symbol);
                            if (this.ptr === this.m_Num) 
                                return true;
                        }
                        if (symbol < 0) 
                            return false;
                        if (symbol >= 17) 
                            this.lastLen = 0;
                        else if (this.ptr === 0) 
                            throw new Error();
                        this.repSymbol = symbol - 16;
                    }
                this.mode = InflaterDynHeader.rEPS;
                break;
            }
            case InflaterDynHeader.rEPS: {{
                        let bits = InflaterDynHeader.repBits[this.repSymbol];
                        let count = input.peekBits(bits);
                        if (count < 0) 
                            return false;
                        input.dropBits(bits);
                        count += InflaterDynHeader.repMin[this.repSymbol];
                        if ((this.ptr + count) > this.m_Num) 
                            throw new Error();
                        while ((count--) > 0) {
                            this.litdistLens[this.ptr++] = this.lastLen;
                        }
                        if (this.ptr === this.m_Num) 
                            return true;
                    }
                this.mode = InflaterDynHeader.lENS;
                break;
            }
            }
        }
    }
    
    buildLitLenTree() {
        let litlenLens = new Uint8Array(this.m_Lnum);
        for(let iii = 0; iii < (this.m_Lnum); iii++) litlenLens[(0) + iii] = this.litdistLens[(0) + iii];
        return new InflaterHuffmanTree(litlenLens);
    }
    
    buildDistTree() {
        let distLens = new Uint8Array(this.m_Dnum);
        for(let iii = 0; iii < (this.m_Dnum); iii++) distLens[(0) + iii] = this.litdistLens[(this.m_Lnum) + iii];
        return new InflaterHuffmanTree(distLens);
    }
    
    static static_constructor() {
        InflaterDynHeader.lNUM = 0;
        InflaterDynHeader.dNUM = 1;
        InflaterDynHeader.bLNUM = 2;
        InflaterDynHeader.bLLENS = 3;
        InflaterDynHeader.lENS = 4;
        InflaterDynHeader.rEPS = 5;
        InflaterDynHeader.repMin = new Int32Array([3, 3, 11]);
        InflaterDynHeader.repBits = new Int32Array([2, 3, 7]);
        InflaterDynHeader.bL_ORDER = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
    }
}


InflaterDynHeader.static_constructor();

module.exports = InflaterDynHeader