using System;
using System.Threading;

namespace AnotherReplayReader.Utils
{
    internal class CancelManager : IDisposable
    {
        private CancellationToken _linkedToken;
        private CancellationTokenSource? _source;

        public CancellationToken Token => Materialize().Token;

        public void Reset(CancellationToken linked)
        {
            _linkedToken = linked;
            if (_source is { } source)
            {
                _source = null;
                try
                {
                    source.Cancel();
                }
                catch (AggregateException e)
                {
                    Debug.Instance.DebugMessage += $"Cancellation failed: {e}";
                }
                source.Dispose();
            }
        }

        public CancellationToken ResetAndGetToken(CancellationToken linked)
        {
            Reset(linked);
            return Token;
        }

        public void Dispose() => Reset(default);

        private CancellationTokenSource Materialize()
        {
            if (_source is null)
            {
                _source = CancellationTokenSource.CreateLinkedTokenSource(_linkedToken);
            }
            return _source;
        }
    }
}