using System.Text;

namespace SoulstormReplayReader.Core.Extensions;

public class ExBinaryReader : BinaryReader
{
    public long Position => BaseStream.Position;
    public long Length => BaseStream.Length;
    public long BytesLeft => Length - Position;
    public bool HasBytes => Position < Length;

    public ExBinaryReader(Stream stream) : base(stream) { }

    public ExBinaryReader(byte[] byteArray) : base(new MemoryStream(byteArray)) { }

    public ExBinaryReader SkipInt32(int count = 1) => Skip(count * 4);

    public ExBinaryReader Skip(int bytesCount)
    {
        BaseStream.Seek(bytesCount, SeekOrigin.Current);
        return this;
    }

    public ExBinaryReader Seek(int offset, SeekOrigin seekOrigin = SeekOrigin.Begin)
    {
        BaseStream.Seek(offset, seekOrigin);
        return this;
    }

    public string ReadNextUnicodeString() => ReadUnicodeString(ReadInt32());

    public string ReadUnicodeString(int length)
    {
        var doubleLength = length * 2;
        var bytes = doubleLength switch
        {
            > 0 and < 0xFF => ReadBytes(stackalloc byte[doubleLength]),
            _ => ReadBytes(doubleLength)
        };

        return Encoding.Unicode.GetString(bytes);
    }

    public string ReadNextAsciiString() => ReadAsciiString(ReadInt32());

    public string ReadAsciiString(int length)
    {
        var bytes = length switch
        {
            > 0 and < 0xFF => ReadBytes(stackalloc byte[length]),
            _ => ReadBytes(length)
        };

        return Encoding.ASCII.GetString(bytes);
    }

    public string ReadCString(int length = 150)
    {
        var bytes = length switch
        {
            > 0 and < 0xFF => ReadBytes(stackalloc byte[length]),
            _ => ReadBytes(length)
        };

        bytes = bytes[..bytes.IndexOf(byte.MinValue)];

        return Encoding.ASCII.GetString(bytes);
    }

    public Span<byte> ReadBytes(Span<byte> buffer)
    {
        BaseStream.ReadExactly(buffer);
        return buffer;
    }
}