using System;

namespace ComponentAce.Compression.Libs.zlib;

public sealed class ZStream
{
	private const int MAX_WBITS = 15;

	private static readonly int DEF_WBITS = 15;

	private const int Z_NO_FLUSH = 0;

	private const int Z_PARTIAL_FLUSH = 1;

	private const int Z_SYNC_FLUSH = 2;

	private const int Z_FULL_FLUSH = 3;

	private const int Z_FINISH = 4;

	private const int MAX_MEM_LEVEL = 9;

	private const int Z_OK = 0;

	private const int Z_STREAM_END = 1;

	private const int Z_NEED_DICT = 2;

	private const int Z_ERRNO = -1;

	private const int Z_STREAM_ERROR = -2;

	private const int Z_DATA_ERROR = -3;

	private const int Z_MEM_ERROR = -4;

	private const int Z_BUF_ERROR = -5;

	private const int Z_VERSION_ERROR = -6;

	public byte[] next_in;

	public int next_in_index;

	public int avail_in;

	public long total_in;

	public byte[] next_out;

	public int next_out_index;

	public int avail_out;

	public long total_out;

	public string msg;

	internal Deflate dstate;

	internal Inflate istate;

	internal int data_type;

	public long adler;

	internal Adler32 _adler = new Adler32();

	public int inflateInit()
	{
		return inflateInit(DEF_WBITS);
	}

	public int inflateInit(int w)
	{
		istate = new Inflate();
		return istate.inflateInit(this, w);
	}

	public int inflate(int f)
	{
		if (istate == null)
		{
			return -2;
		}
		return istate.inflate(this, f);
	}

	public int inflateEnd()
	{
		if (istate == null)
		{
			return -2;
		}
		int result = istate.inflateEnd(this);
		istate = null;
		return result;
	}

	public int inflateSync()
	{
		if (istate == null)
		{
			return -2;
		}
		return istate.inflateSync(this);
	}

	public int inflateSetDictionary(byte[] dictionary, int dictLength)
	{
		if (istate == null)
		{
			return -2;
		}
		return istate.inflateSetDictionary(this, dictionary, dictLength);
	}

	public int deflateInit(int level)
	{
		return deflateInit(level, 15);
	}

	public int deflateInit(int level, int bits)
	{
		dstate = new Deflate();
		return dstate.deflateInit(this, level, bits);
	}

	public int deflate(int flush)
	{
		if (dstate == null)
		{
			return -2;
		}
		return dstate.deflate(this, flush);
	}

	public int deflateEnd()
	{
		if (dstate == null)
		{
			return -2;
		}
		int result = dstate.deflateEnd();
		dstate = null;
		return result;
	}

	public int deflateParams(int level, int strategy)
	{
		if (dstate == null)
		{
			return -2;
		}
		return dstate.deflateParams(this, level, strategy);
	}

	public int deflateSetDictionary(byte[] dictionary, int dictLength)
	{
		if (dstate == null)
		{
			return -2;
		}
		return dstate.deflateSetDictionary(this, dictionary, dictLength);
	}

	internal void flush_pending()
	{
		int pending = dstate.pending;
		if (pending > avail_out)
		{
			pending = avail_out;
		}
		if (pending != 0)
		{
			if (dstate.pending_buf.Length > dstate.pending_out && next_out.Length > next_out_index && dstate.pending_buf.Length >= dstate.pending_out + pending)
			{
				_ = next_out.Length;
				_ = next_out_index + pending;
			}
			Array.Copy(dstate.pending_buf, dstate.pending_out, next_out, next_out_index, pending);
			next_out_index += pending;
			dstate.pending_out += pending;
			total_out += pending;
			avail_out -= pending;
			dstate.pending -= pending;
			if (dstate.pending == 0)
			{
				dstate.pending_out = 0;
			}
		}
	}

	internal int read_buf(byte[] buf, int start, int size)
	{
		int num = avail_in;
		if (num > size)
		{
			num = size;
		}
		if (num == 0)
		{
			return 0;
		}
		avail_in -= num;
		if (dstate.noheader == 0)
		{
			adler = _adler.adler32(adler, next_in, next_in_index, num);
		}
		Array.Copy(next_in, next_in_index, buf, start, num);
		next_in_index += num;
		total_in += num;
		return num;
	}

	public void free()
	{
		next_in = null;
		next_out = null;
		msg = null;
		_adler = null;
	}
}