using Borepin.Service;
using FabAccessAPI;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Threading.Tasks;

namespace Borepin.Base
{
    /// <summary>
    /// Base for all BFFH Based PageModels
    /// </summary>
    public abstract class ConnectionModelBase : PageModelBase
    {
        #region Private Fields
        protected readonly IAPI _API;
        protected readonly IAPIService _APIService;
        #endregion

        #region Constructors
        protected ConnectionModelBase(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService)
        {
            _APIService = apiService;

            _API = apiService.GetAPI();
            _API.ConnectionStatusChanged += OnConnectionStatusChanged;

            IsConnected = _API.IsConnected;
        }
        #endregion

        #region Methods
        public async void OnConnectionStatusChanged(object sender, ConnectionStatusChange args)
        {
            switch(args)
            {
                case ConnectionStatusChange.Connected:
                    IsConnected = true;
                    try
                    {
                        await LoadAPIData().ConfigureAwait(false);
                    }
                    catch
                    {
                        IsConnected = false;
                        await _API.Disconnect().ConfigureAwait(false);
                        _API.UnbindAllEvents();
                    }
                    break;
                case ConnectionStatusChange.Reconnected:
                    try
                    {
                        await ReloadAPIData().ConfigureAwait(false);
                    }
                    catch
                    {
                        IsConnected = false;
                        await _API.Disconnect().ConfigureAwait(false);
                        _API.UnbindAllEvents();
                    }
                    break;
                case ConnectionStatusChange.ConnectionLoss:
                    try
                    {
                        await _API.Reconnect().ConfigureAwait(false);
                    }
                    catch
                    {
                        IsConnected = false;
                        await _API.Disconnect().ConfigureAwait(false);
                        _API.UnbindAllEvents();
                    }
                    break;
                case ConnectionStatusChange.Disconnected:
                    IsConnected = false;
                    break;
            }
        }

        public virtual Task LoadAPIData()
        {
            return Task.CompletedTask;
        }
        public virtual Task ReloadAPIData()
        {
            return Task.CompletedTask;
        }
        #endregion

        #region Fields
        /// <summary>
        /// PageModel is Connected
        /// </summary>
        private bool _IsConnected = true;
        public bool IsConnected
        {
            get => _IsConnected;
            set => SetProperty(ref _IsConnected, value);
        }
        #endregion

        #region INavigationAware
        public override async Task OnNavigatedToVirtual(INavigationParameters parameters)
        {
            await base.OnNavigatedToVirtual(parameters).ConfigureAwait(false);

            if(_API.IsConnected)
            {
                try
                {
                    await LoadAPIData().ConfigureAwait(false);
                }
                catch(Exception ex)
                {
                    IsConnected = false;
                    await _API.Disconnect().ConfigureAwait(false);
                    _API.UnbindAllEvents();
                }
            }
        }
        #endregion
    }
}