using System;
using System.IO;
using System.Runtime.InteropServices;
namespace PriFileFormat
{
	public class SubStream: Stream
	{
		Stream baseStream;
		long subStreamPosition;
		long subStreamLength;

		public SubStream (Stream baseStream, long subStreamPosition, long subStreamLength)
		{
			this.baseStream = baseStream;
			this.subStreamPosition = subStreamPosition;
			this.subStreamLength = subStreamLength;
		}

		public long SubStreamPosition => subStreamPosition;

		public override bool CanRead => baseStream.CanRead;

		public override bool CanSeek => baseStream.CanSeek;

		public override bool CanWrite => false;

		public override long Length => subStreamLength;

		public override long Position
		{
			get { return baseStream.Position - subStreamPosition; }
			set { baseStream.Position = subStreamPosition + value; }
		}

		public override void Flush ()
		{
		}

		public override int Read (byte [] buffer, int offset, int count)
		{
			if (Position < 0)
				throw new InvalidOperationException ("Cannot read when position is negative.");
			if (Position + count > subStreamLength)
				count = (int)(subStreamLength - Position);

			return baseStream.Read (buffer, offset, count);
		}

		public override long Seek (long offset, SeekOrigin origin)
		{
			switch (origin)
			{
				case SeekOrigin.Begin:
					return baseStream.Seek (subStreamPosition + offset, SeekOrigin.Begin) - subStreamPosition;
				case SeekOrigin.Current:
					return baseStream.Seek (offset, SeekOrigin.Current) - subStreamPosition;
				case SeekOrigin.End:
					return baseStream.Seek (subStreamPosition + subStreamLength + offset, SeekOrigin.Begin) - subStreamPosition;
				default:
					throw new ArgumentException ("Invalid origin.", nameof (origin));
			}
		}

		public override void SetLength (long value)
		{
			throw new NotSupportedException ();
		}

		public override void Write (byte [] buffer, int offset, int count)
		{
			throw new NotSupportedException ();
		}

		~SubStream () { baseStream = null; }
	}
}
