/*
 * 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
 */

package com.pullenti.unitext.internal.zip;

public class InflaterDynHeader {

    private static final int lNUM = 0;

    private static final int dNUM = 1;

    private static final int bLNUM = 2;

    private static final int bLLENS = 3;

    private static final int lENS = 4;

    private static final int rEPS = 5;

    private static int[] repMin;

    private static int[] repBits;

    private static int[] bL_ORDER;

    public InflaterDynHeader() {
    }

    public boolean decode(StreamManipulator input) throws Exception {
        for (; ; ) {
            switch (mode) { 
            case lNUM:
                m_Lnum = input.peekBits(5);
                if (m_Lnum < 0) 
                    return false;
                m_Lnum += 257;
                input.dropBits(5);
                mode = dNUM;
                break;
            case dNUM:
                m_Dnum = input.peekBits(5);
                if (m_Dnum < 0) 
                    return false;
                m_Dnum++;
                input.dropBits(5);
                m_Num = m_Lnum + m_Dnum;
                litdistLens = new byte[m_Num];
                mode = bLNUM;
                break;
            case bLNUM:
                m_Blnum = input.peekBits(4);
                if (m_Blnum < 0) 
                    return false;
                m_Blnum += 4;
                input.dropBits(4);
                blLens = new byte[19];
                ptr = 0;
                mode = bLLENS;
                break;
            case bLLENS:
                while (ptr < m_Blnum) {
                    int len = input.peekBits(3);
                    if (len < 0) 
                        return false;
                    input.dropBits(3);
                    blLens[bL_ORDER[ptr]] = (byte)len;
                    ptr++;
                }
                blTree = new InflaterHuffmanTree(blLens);
                blLens = null;
                ptr = 0;
                mode = lENS;
                break;
            case lENS:{
                        int symbol;
                        while ((((((symbol = blTree.getSymbol(input)))) & (~15))) == 0) {
                            litdistLens[ptr++] = (lastLen = (byte)symbol);
                            if (ptr == m_Num) 
                                return true;
                        }
                        if (symbol < 0) 
                            return false;
                        if (symbol >= 17) 
                            lastLen = (byte)0;
                        else if (ptr == 0) 
                            throw new Exception();
                        repSymbol = symbol - 16;
                    }
                mode = rEPS;
                break;
            case rEPS:{
                        int bits = repBits[repSymbol];
                        int count = input.peekBits(bits);
                        if (count < 0) 
                            return false;
                        input.dropBits(bits);
                        count += repMin[repSymbol];
                        if ((ptr + count) > m_Num) 
                            throw new Exception();
                        while ((count--) > 0) {
                            litdistLens[ptr++] = lastLen;
                        }
                        if (ptr == m_Num) 
                            return true;
                    }
                mode = lENS;
                break;
        }
        }
    }

    public InflaterHuffmanTree buildLitLenTree() {
        byte[] litlenLens = new byte[m_Lnum];
        for(int iii = 0; iii < (m_Lnum); iii++) litlenLens[(0) + iii] = litdistLens[(0) + iii];
        return new InflaterHuffmanTree(litlenLens);
    }

    public InflaterHuffmanTree buildDistTree() {
        byte[] distLens = new byte[m_Dnum];
        for(int iii = 0; iii < (m_Dnum); iii++) distLens[(0) + iii] = litdistLens[(m_Lnum) + iii];
        return new InflaterHuffmanTree(distLens);
    }

    private byte[] blLens;

    private byte[] litdistLens;

    private InflaterHuffmanTree blTree;

    private int mode;

    private int m_Lnum;

    private int m_Dnum;

    private int m_Blnum;

    private int m_Num;

    private int repSymbol;

    private byte lastLen;

    private int ptr;

    
    static {
        repMin = new int[] {3, 3, 11};
        repBits = new int[] {2, 3, 7};
        bL_ORDER = new int[] {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
    }
}
