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

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace Pullenti.Unitext.Internal.Misc
{
    class LzwDecoder
    {
        public byte[] Decode(byte[] data)
        {
            MemoryStream outputStream = new MemoryStream();
            this._initializeDictionary();
            this.m_Data = data;
            m_BytePointer = 0;
            m_DataBuffer = 0;
            m_NextBits = 0;
            int code;
            int oldCode = 0;
            byte[] str;
            int inits = 0;
            while ((((code = this._getNextCode()))) != 257) 
            {
                if (code == 256) 
                {
                    this._initializeDictionary();
                    inits++;
                    code = this._getNextCode();
                    if (code == 257) 
                        break;
                    if (code == 256) 
                    {
                    }
                    outputStream.Write(m_StringTable[code], 0, m_StringTable[code].Length);
                    oldCode = code;
                }
                else if (code < m_TableIndex) 
                {
                    str = m_StringTable[code];
                    outputStream.Write(str, 0, str.Length);
                    this._addEntry(m_StringTable[oldCode], str[0]);
                    oldCode = code;
                }
                else 
                {
                    str = m_StringTable[oldCode];
                    outputStream.Write(str, 0, str.Length);
                    this._addEntry(str, str[0]);
                    outputStream.WriteByte(str[0]);
                    oldCode = code;
                }
            }
            if (outputStream.Length > 0) 
                return outputStream.ToArray();
            return null;
        }
        void _initializeDictionary()
        {
            if (m_StringTable == null) 
            {
                m_StringTable = new List<byte[]>();
                for (int i = 0; i < 8192; i++) 
                {
                    m_StringTable.Add(null);
                }
                for (int i = 0; i < 256; i++) 
                {
                    m_StringTable[i] = new byte[(int)1];
                    m_StringTable[i][0] = (byte)i;
                }
            }
            else 
                for (int i = 256; i < m_StringTable.Count; i++) 
                {
                    m_StringTable[i] = null;
                }
            m_TableIndex = 258;
            m_BitsToGet = 9;
        }
        void _addEntry(byte[] oldstring, byte newstring)
        {
            int length = oldstring.Length;
            byte[] str = new byte[(int)(length + 1)];
            Array.Copy(oldstring, 0, str, 0, length);
            str[length] = newstring;
            m_StringTable[m_TableIndex++] = str;
            if (m_TableIndex == 511) 
                m_BitsToGet = 10;
            else if (m_TableIndex == 1023) 
                m_BitsToGet = 11;
            else if (m_TableIndex == 2047) 
                m_BitsToGet = 12;
        }
        int _getNextCode()
        {
            if (m_BytePointer >= m_Data.Length) 
                return 257;
            m_DataBuffer = (m_DataBuffer << 8) | ((m_Data[m_BytePointer++] & 0xff));
            m_NextBits += 8;
            if (m_NextBits < m_BitsToGet) 
            {
                if (m_BytePointer >= m_Data.Length) 
                    return 257;
                m_DataBuffer = (m_DataBuffer << 8) | ((m_Data[m_BytePointer++] & 0xff));
                m_NextBits += 8;
            }
            int code = ((m_DataBuffer >> ((m_NextBits - m_BitsToGet)))) & m_AndTable[m_BitsToGet - 9];
            m_NextBits -= m_BitsToGet;
            if (code == 256) 
            {
            }
            return code;
        }
        int[] m_AndTable = new int[] {511, 1023, 2047, 4095};
        List<byte[]> m_StringTable;
        byte[] m_Data;
        int m_TableIndex;
        int m_BitsToGet = 9;
        int m_BytePointer;
        int m_DataBuffer = 0;
        int m_NextBits = 0;
    }
}