using System;
using System.IO;

namespace ComponentAce.Compression.Libs.zlib
{
    public class ZOutputStream : Stream
    {
    	protected internal ZStream z = new ZStream();

    	protected internal int bufsize = 4096;

    	protected internal int flush_Renamed_Field;

    	protected internal byte[] buf;

    	protected internal byte[] buf1 = new byte[1];

    	protected internal bool compress;

    	private Stream out_Renamed;

    	public virtual int FlushMode
    	{
    		get
    		{
    			return flush_Renamed_Field;
    		}
    		set
    		{
    			flush_Renamed_Field = value;
    		}
    	}

    	public virtual long TotalIn => z.total_in;

    	public virtual long TotalOut => z.total_out;

    	public override bool CanRead => false;

    	public override bool CanSeek => false;

    	public override bool CanWrite => false;

    	public override long Length => 0L;

    	public override long Position
    	{
    		get
    		{
    			return 0L;
    		}
    		set
    		{
    		}
    	}

    	private void InitBlock()
    	{
    		flush_Renamed_Field = 0;
    		buf = new byte[bufsize];
    	}

    	public ZOutputStream(Stream out_Renamed)
    	{
    		InitBlock();
    		this.out_Renamed = out_Renamed;
    		z.inflateInit();
    		compress = false;
    	}

    	public ZOutputStream(Stream out_Renamed, int level)
    	{
    		InitBlock();
    		this.out_Renamed = out_Renamed;
    		z.deflateInit(level);
    		compress = true;
    	}

    	public void WriteByte(int b)
    	{
    		buf1[0] = (byte)b;
    		Write(buf1, 0, 1);
    	}

    	public override void WriteByte(byte b)
    	{
    		WriteByte(b);
    	}

    	public override void Write(byte[] b1, int off, int len)
    	{
    		if (len == 0)
    		{
    			return;
    		}
    		byte[] array = new byte[b1.Length];
    		Array.Copy(b1, 0, array, 0, b1.Length);
    		z.next_in = array;
    		z.next_in_index = off;
    		z.avail_in = len;
    		do
    		{
    			z.next_out = buf;
    			z.next_out_index = 0;
    			z.avail_out = bufsize;
    			int num = ((!compress) ? z.inflate(flush_Renamed_Field) : z.deflate(flush_Renamed_Field));
    			if (num != 0 && num != 1)
    			{
    				throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
    			}
    			out_Renamed.Write(buf, 0, bufsize - z.avail_out);
    		}
    		while (z.avail_in > 0 || z.avail_out == 0);
    	}

    	public virtual void finish()
    	{
    		do
    		{
    			z.next_out = buf;
    			z.next_out_index = 0;
    			z.avail_out = bufsize;
    			int num = ((!compress) ? z.inflate(4) : z.deflate(4));
    			if (num != 1 && num != 0)
    			{
    				throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
    			}
    			if (bufsize - z.avail_out > 0)
    			{
    				out_Renamed.Write(buf, 0, bufsize - z.avail_out);
    			}
    		}
    		while (z.avail_in > 0 || z.avail_out == 0);
    		try
    		{
    			Flush();
    		}
    		catch
    		{
    		}
    	}

    	public virtual void end()
    	{
    		if (compress)
    		{
    			z.deflateEnd();
    		}
    		else
    		{
    			z.inflateEnd();
    		}
    		z.free();
    		z = null;
    	}

    	public override void Close()
    	{
    		try
    		{
    			finish();
    		}
    		catch
    		{
    		}
    		finally
    		{
    			end();
    			out_Renamed.Close();
    			out_Renamed = null;
    		}
    	}

    	public override void Flush()
    	{
    		out_Renamed.Flush();
    	}

    	public override int Read(byte[] buffer, int offset, int count)
    	{
    		return 0;
    	}

    	public override void SetLength(long value)
    	{
    	}

    	public override long Seek(long offset, SeekOrigin origin)
    	{
    		return 0L;
    	}
    }
}