using System;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace FasdDesktopUi.Basics.Services.Models
{
    internal interface ITicketOverviewTimer
    {
        TimeSpan Interval { get; set; }

        bool IsEnabled { get; }

        void Start();

        void Stop();
    }

    internal interface ITicketOverviewDispatcher
    {
        Task InvokeAsync(Action action);

        Task InvokeAsync(Func<Task> action);

        ITicketOverviewTimer CreateTimer(TimeSpan interval, Action tick);
    }

    internal sealed class TicketOverviewDispatcher : ITicketOverviewDispatcher
    {
        private readonly Dispatcher _dispatcher;

        internal TicketOverviewDispatcher(Dispatcher dispatcher)
        {
            _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
        }

        public Task InvokeAsync(Action action)
        {
            return _dispatcher.InvokeAsync(action, DispatcherPriority.Background).Task;
        }

        public Task InvokeAsync(Func<Task> action)
        {
            return _dispatcher.InvokeAsync(action, DispatcherPriority.Background).Task.Unwrap();
        }

        public ITicketOverviewTimer CreateTimer(TimeSpan interval, Action tick)
        {
            var timer = new DispatcherTimer(interval, DispatcherPriority.Background, (sender, args) => tick?.Invoke(), _dispatcher)
            {
                IsEnabled = false
            };
            return new TicketOverviewTimer(timer);
        }
    }

    internal sealed class TicketOverviewTimer : ITicketOverviewTimer
    {
        private readonly DispatcherTimer _timer;

        internal TicketOverviewTimer(DispatcherTimer timer)
        {
            _timer = timer ?? throw new ArgumentNullException(nameof(timer));
        }

        public TimeSpan Interval
        {
            get => _timer.Interval;
            set => _timer.Interval = value;
        }

        public bool IsEnabled => _timer.IsEnabled;

        public void Start()
        {
            _timer.Start();
        }

        public void Stop()
        {
            _timer.Stop();
        }
    }
}
