using System.Runtime.InteropServices;
using System.Text;

namespace Steamworks
{
	internal unsafe class Utf8StringToNative : ICustomMarshaler
	{
		public IntPtr MarshalManagedToNative( object managedObj )
		{
			if ( managedObj == null )
				return IntPtr.Zero;

			if ( managedObj is string str )
			{
				fixed ( char* strPtr = str )
				{
					int len = Encoding.UTF8.GetByteCount( str );
					var mem = Marshal.AllocHGlobal( len + 1 );

					var wlen = System.Text.Encoding.UTF8.GetBytes( strPtr, str.Length, (byte*)mem, len + 1 );

					((byte*)mem)[wlen] = 0;

					return mem;
				}
			}

			return IntPtr.Zero;
		}

		public object MarshalNativeToManaged( IntPtr pNativeData ) => throw new System.NotImplementedException();
		public void CleanUpNativeData( IntPtr pNativeData ) => Marshal.FreeHGlobal( pNativeData );
		public void CleanUpManagedData( object managedObj ) => throw new System.NotImplementedException();
		public int GetNativeDataSize() => -1;

		public static ICustomMarshaler GetInstance( string cookie ) => new Utf8StringToNative();
	}

	internal struct Utf8StringPointer
	{
#pragma warning disable 649
		internal IntPtr ptr;
#pragma warning restore 649

		public unsafe static implicit operator string( Utf8StringPointer p )
		{
			if ( p.ptr == IntPtr.Zero )
				return null;

			var bytes = (byte*)p.ptr;

			var dataLen = 0;
			while ( dataLen < 1024 * 1024 * 64 )
			{
				if ( bytes[dataLen] == 0 )
					break;

				dataLen++;
			}

			return Encoding.UTF8.GetString( bytes, dataLen );
		}
	}
}
