using System;
using System.Buffers;
using System.Runtime.CompilerServices;
/*https://github.com/sidristij/memory-pools*/
namespace MemoryPools.Memory
{
    /// 
    ///     Encapsulates manual memory management mechanism. Holds
    ///     IMemoryOwner instance goes to GC (link = null!) only when
    ///     all owning entities called Dispose() method. This means,
    ///     that only this mechanism should be used for covering
    ///     managed instances.
    /// 
    public sealed class CountdownMemoryOwner : IMemoryOwner
	{
		private int _length;
		private int _offset;
		private int _owners;
		private T[] _arr;
		private CountdownMemoryOwner _parent;
		private Memory _memory;
		public Memory Memory
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get => _memory;
			private set => _memory = value;
		}
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal CountdownMemoryOwner Init(CountdownMemoryOwner parent, int offset, int length, bool defaultOwner = true)
		{
			_owners = defaultOwner ? 1 : 0;
			_offset = offset;
			_length = length;
			_parent = parent;
			_parent.AddOwner();
			Memory = _parent.Memory.Slice(_offset, _length);
			return this;
		}
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal CountdownMemoryOwner Init(T[] array, int length)
		{
			_owners = 1;
			_offset = 0;
			_length = length;
			_parent = default!;
			_arr = array;
			Memory = _arr.AsMemory(0, _length);
			return this;
		}
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void AddOwner() => _owners++;
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Dispose()
		{
			_owners--;
			if (_owners > 0)
			{
				return;
			}
			if (_parent != default)
			{
				_parent.Dispose();
				_parent = null!;
			}
			else
			{
				ArrayPool.Shared.Return(_arr);
			}
			Pool>.Return(this);
		}
	}
}