using Borepin.Base;
using Prism.Commands;
using Prism.Navigation;
using System.Windows.Input;
using FabAccessAPI.Schema;
using Prism.Services;
using Borepin.Service;
using Capnp.Rpc;
using System;
using static FabAccessAPI.Schema.UserSystem.ManageInterface;
using static FabAccessAPI.Schema.UserSystem.ManageInterface.AddUserError;
using Xamarin.Forms;

namespace Borepin.PageModel
{
    public class AddUserPageModel : ConnectionModelBase
    {
        #region Contructors
        public AddUserPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService)
        {
            AddUserCommand = new DelegateCommand(AddUserCommandExecute);
        }
        #endregion

        #region Fields
        private string _Username;
        public string Username
        {
            get => _Username;
            set => SetProperty(ref _Username, value);
        }

        private string _Password;
        public string Password
        {
            get => _Password;
            set => SetProperty(ref _Password, value);
        }
        #endregion

        #region Commands
        private ICommand _AddUserCommand;

        public ICommand AddUserCommand
        {
            get => _AddUserCommand;
            set => SetProperty(ref _AddUserCommand, value);
        }

        public async void AddUserCommandExecute()
        {
            IsBusy = true;
            
            if(_API.IsConnected)
            {
                try
                {
                    Fallible<User, AddUserError> user_result = await _API.Session.UserSystem.Manage.AddUserFallible(Username, Password).ConfigureAwait(false);
                    if(user_result.Failed != null)
                    {
                        switch(user_result.Failed.Error)
                        {
                            case AddUserErrorEnum.alreadyExists:
                                Device.BeginInvokeOnMainThread(async () =>
                                {
                                    await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.ALERT_AddUserFailed, Resources.Text.TextResource.ALERT_UserExist, Resources.Text.TextResource.OK).ConfigureAwait(false);

                                    IsBusy = false;
                                });
                                break;
                            case AddUserErrorEnum.usernameInvalid:
                                Device.BeginInvokeOnMainThread(async () =>
                                {
                                    await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.ALERT_AddUserFailed, Resources.Text.TextResource.ALERT_UsernameInvalid, Resources.Text.TextResource.OK).ConfigureAwait(false);

                                    IsBusy = false;
                                });
                                break;
                            case AddUserErrorEnum.passwordInvalid:
                                Device.BeginInvokeOnMainThread(async () =>
                                {
                                    await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.ALERT_AddUserFailed, Resources.Text.TextResource.ALERT_PasswordInvalid, Resources.Text.TextResource.OK).ConfigureAwait(false);

                                    IsBusy = false;
                                });
                                break;
                        }
                    }
                    else
                    {
                        NavigationParameters parameters = new NavigationParameters
                        {
                            { "instance", user_result.Successful.Username },
                        };

                        Device.BeginInvokeOnMainThread(async () =>
                        {
                            INavigationResult result = await _NavigationService.NavigateAsync("/MainPage/NavigationPage/UserListPage/UserPage", parameters).ConfigureAwait(false);
                            if (result.Exception != null)
                            {
                                Log.Fatal(result.Exception, "Navigating failed");
                            }
                        });
                    }
                }
                catch (RpcException exception) when (string.Equals(exception.Message, "RPC connection is broken. Task would never return.", StringComparison.Ordinal))
                {
                    Log.Debug("RPC Connection Loss");
                }
            }

            IsBusy = false;
        }
        #endregion
    }
}
