using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Unity.Collections.LowLevel.Unsafe;
namespace Unity.Burst
{
    /// 
    /// Base interface for a function pointer.
    /// 
    public interface IFunctionPointer
    {
        /// 
        /// Converts a pointer to a function pointer.
        /// 
        /// The native pointer.
        /// An instance of this interface.
        [Obsolete("This method will be removed in a future version of Burst")]
        IFunctionPointer FromIntPtr(IntPtr ptr);
    }
    /// 
    /// A function pointer that can be used from a Burst Job or from regular C#.
    /// It needs to be compiled through 
    /// 
    /// Type of the delegate of this function pointer
    public readonly struct FunctionPointer : IFunctionPointer
    {
        // DOTSPLAYER's shim package relies on Burst for it's jobs code
        // so Burst does not see the DOTSPLAYER definition of this attribute
        [NativeDisableUnsafePtrRestriction]
        private readonly IntPtr _ptr;
        /// 
        /// Creates a new instance of this function pointer with the following native pointer.
        /// 
        /// Native Pointer
        public FunctionPointer(IntPtr ptr)
        {
            _ptr = ptr;
        }
        /// 
        /// Gets the underlying pointer.
        /// 
        public IntPtr Value => _ptr;
        [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
        private void CheckIsCreated()
        {
            if (!IsCreated)
            {
                throw new NullReferenceException("Object reference not set to an instance of an object");
            }
        }
        /// 
        /// Gets the delegate associated to this function pointer in order to call the function pointer.
        /// This delegate can be called from a Burst Job or from regular C#.
        /// If calling from regular C#, it is recommended to cache the returned delegate of this property
        /// instead of using this property every time you need to call the delegate.
        /// 
        public T Invoke
        {
            get
            {
                CheckIsCreated();
                return Marshal.GetDelegateForFunctionPointer(_ptr);
            }
        }
        /// 
        /// Whether the function pointer is valid.
        /// 
        public bool IsCreated => _ptr != IntPtr.Zero;
		/// 
        /// Converts a pointer to a function pointer.
        /// 
        /// The native pointer.
        /// An instance of this interface.
        IFunctionPointer IFunctionPointer.FromIntPtr(IntPtr ptr) => new FunctionPointer(ptr);
    }
}