using System;
using System.Runtime.InteropServices;

namespace CPF.Mac.ObjCRuntime
{
	public struct BlockLiteral
	{
		public IntPtr isa;

		public BlockFlags flags;

		public int reserved;

		public IntPtr invoke;

		public IntPtr block_descriptor;

		public IntPtr local_handle;

		public IntPtr global_handle;

		internal static IntPtr block_class;

		internal static BlockDescriptor global_descriptor;

		internal static IntPtr global_descriptor_ptr;

		static BlockLiteral()
		{
			block_class = Class.GetHandle("__NSStackBlock");
			global_descriptor = BlockDescriptor.CreateDescriptor();
			global_descriptor_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * 2 + Marshal.SizeOf(typeof(IntPtr)) * 2);
			Marshal.StructureToPtr(global_descriptor, global_descriptor_ptr, fDeleteOld: false);
		}

		public void SetupBlock(Delegate trampoline, Delegate userDelegate)
		{
			isa = block_class;
			invoke = Marshal.GetFunctionPointerForDelegate(trampoline);
			local_handle = (IntPtr)GCHandle.Alloc(userDelegate);
			global_handle = IntPtr.Zero;
			flags = (BlockFlags.BLOCK_HAS_COPY_DISPOSE | BlockFlags.BLOCK_HAS_DESCRIPTOR);
			block_descriptor = global_descriptor_ptr;
		}

		public void CleanupBlock()
		{
			GCHandle.FromIntPtr(local_handle).Free();
		}
	}
}
