namespace InnovEnergy.Lib.Utils;

public class Disposable : IDisposable
{
    private Action? _Dispose;

    public Disposable(Action dispose)
    {
        _Dispose = dispose;
    }

    public void Dispose() => Interlocked.Exchange(ref _Dispose, null)?.Invoke();

    public static Disposable<T> Create<T>(T t, Action dispose) => new Disposable<T>(t, dispose);
}

public class Disposable<T> : IDisposable
{
    private Action? _Dispose;
    private readonly T _Value;

    public T Value
    {
        get
        {
            if (_Dispose == null)
                throw new ObjectDisposedException(nameof(Disposable<T>));

            return _Value;
        }
    }

    public Disposable(T t, Action dispose)
    {
        _Dispose = dispose;
        _Value = t;
    }

    public void Dispose() => Interlocked.Exchange(ref _Dispose, null)?.Invoke();

    public Disposable<T> BeforeDisposeDo(Action action)
    {
        return new Disposable<T>(Value, () =>
        {
            action();
            Dispose();
        });
    }


    public static implicit operator T(Disposable<T> t) => t.Value;

    public override String ToString() => Value?.ToString() ?? "<null>";
}