using Microsoft.AspNetCore.DataProtection.KeyManagement;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Exceptions;

namespace XF.Domain.Locks
{
    public interface IDistributedLock
    {
        public bool Acquire(string key, TimeSpan expired);

        public Task<bool> AcquireAsync(string key, TimeSpan expired, CancellationToken cancellationToken);

        public void Release(string key);

        public Task ReleaseAsync(string key, CancellationToken cancellationToken);
    }

    public class LockManager : IDisposable
    {
        private readonly IDistributedLock _locker;
        private readonly string _key;

        public LockManager(IDistributedLock locker, string key)
        {
            _locker = locker;
            _key = key;
        }

        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
        public void Dispose()
        {
            _locker.Release(_key);
        }

        public void InvokeInLock(Action doSome, TimeSpan expired)
        {
            if (_locker.Acquire(_key, expired))
            {
                try
                {
                    doSome();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
                finally
                {
                    _locker.Release(_key);
                }
            }
            else
            {
                throw new UserFriendlyException("系统忙，请稍后重试");
            }
        }

        public async Task InvokeInLockAsync(Func<CancellationToken, Task> doSome, TimeSpan expired, CancellationToken cancellationToken)
        {
            if (await _locker.AcquireAsync(_key, expired, cancellationToken))
            {
                try
                {
                    await doSome(cancellationToken);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
                finally
                {
                    await _locker.ReleaseAsync(_key, cancellationToken);
                }
            }
            else
            {
                throw new UserFriendlyException("系统忙，请稍后重试");
            }
        }
    }
}
