using System;
using System.Runtime.InteropServices;
using Decal.Interop.Dat;

namespace Decal.DecalDat
{
    [ComVisible(true)]
    [Guid("9F7F6CD9-D164-418D-8CB5-3B9ACD70BEAF")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("DecalDat.DatStream")]
    public class DatStreamImpl : IDatStream
    {
        private DatFileEntry _file;

        internal void Load(DatFileEntry file)
        {
            _file = file;
        }

        public int Size => _file?.Size ?? 0;

        public int Tell => _file?.Tell ?? 0;

        public void Skip(int Bytes)
        {
            _file?.Skip(Bytes);
        }

        public void Restart()
        {
            _file?.Reset();
        }

        public void ReadBinary(int Bytes, ref byte Buffer)
        {
            if (_file == null) return;

            var buf = new byte[Bytes];
            _file.Read(buf, 0, Bytes);

            // Copy to unmanaged buffer starting at ref Buffer
            Marshal.Copy(buf, 0, GetBufferPtr(ref Buffer), Bytes);
        }

        public string Read(int Bytes)
        {
            if (_file == null) return string.Empty;

            var buf = new byte[Bytes];
            int read = _file.Read(buf, 0, Bytes);

            // Return as binary BSTR (same as SysAllocStringByteLen in C++)
            unsafe
            {
                fixed (byte* p = buf)
                {
                    return Marshal.PtrToStringAnsi(new IntPtr(p), read);
                }
            }
        }

        private static unsafe IntPtr GetBufferPtr(ref byte buffer)
        {
            fixed (byte* p = &buffer)
            {
                return new IntPtr(p);
            }
        }
    }
}
