using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;

namespace Beam.Models {
    public sealed class Fragment<T>(int size) {
        public int Size => FragmentBag.Count;
        public int MaxSize { get; } = size;
        private ConcurrentBag<T> FragmentBag { get; set; } = new();
        public bool TryTake([NotNullWhen(true)] out T? shard) {
            return FragmentBag.TryTake(out shard) && shard != null;
        }

        private bool? Complete = false;
        public bool IsComplete => Complete ?? Size == MaxSize;

        private bool UpdaterLocked = false;

        public static bool TryAcquireUpdater(Fragment<T> fragment, [NotNullWhen(true)] out Action<T>? updater) {
            updater = null;
            if (Interlocked.CompareExchange(ref fragment.UpdaterLocked, true, false) == true) 
                // equivalent to : fragment.UpdaterLocked == true, side-effect: sets fragment.UpdaterLocked to true
                return false;
            updater = fragment.FragmentBag.Add;
            return true;
        }
        public static bool TryReleaseUpdater(Fragment<T> fragment, Action<T> updater) {
            if (updater == fragment.FragmentBag.Add) {
                Interlocked.Exchange(ref fragment.UpdaterLocked, false);
                return true;
            }
            return false;
        }
        public static void SetComplete(Fragment<T> fragment, bool status) {
            fragment.Complete = status;
        }
    }
}
