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

namespace eSuite.WorkBench.WpfHelper
{
    public abstract class AsyncCommandBase : ICommand
    {
        private bool _isExecuting;
        private bool _isEnabled = true;
        private readonly Action<Exception> _onException;
        private readonly Action _onSuccess;

        public event EventHandler<FeedbackEventArgs> FeedbackMessage;
        protected void DoFeedbackMessage(string message)
        {
            if (FeedbackMessage != null)
            {
                var feedbackEventArgs = new FeedbackEventArgs
                {
                    Message = message
                };


                FeedbackMessage(this, feedbackEventArgs);
            }
        }
        private bool IsExecuting
        {
            get => _isExecuting;
            set
            {
                _isExecuting = value;
                CommandManager.InvalidateRequerySuggested();
            }
        }

        public bool IsEnabled
        {
            get => _isEnabled;
            set
            {
                _isEnabled = value;
                CommandManager.InvalidateRequerySuggested();
            }
        }

        public event EventHandler CanExecuteChanged
        {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }

        public AsyncCommandBase(Action<Exception> onException, Action onSuccess = null)
        {
            _onException = onException;
            _onSuccess = onSuccess;
        }

        public virtual bool CanExecute(object parameter)
        {
            return !IsExecuting && IsEnabled;
        }
        
        public async void Execute(object parameter)
        {
            IsExecuting = true;
            try
            {
                await ExecuteAsync(parameter);
            }
            catch (Exception ex)
            {
                _onException.Invoke(ex);
            }
            finally
            {
                IsExecuting = false;
            }
            _onSuccess?.Invoke();
        }

        protected abstract Task ExecuteAsync(object parameter);
    }
}
