using Borepin.Base;
using Borepin.Service;
using Capnp.Rpc;
using FabAccessAPI.Schema;
using Prism.Commands;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Borepin.ViewModel
{
    public class PermissionSelectViewModel : ConnectionModelBase, IDisposable
    {
        #region Private Fields
        private User _User;
        private Role _Role;
        #endregion

        #region Constructors
        public PermissionSelectViewModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService)
        {
            UpdateRoleCommand = new DelegateCommand(UpdateRoleCommandExecute);
        }
        #endregion

        #region LoadData
        public override Task LoadInstance(object instance)
        {
            if(instance is object[])
            {
                object[] array = instance as object[];
                if (array[0] is Role && array[1] is User && array[2] is bool)
                {
                    _Role = array[0] as Role;
                    _User = array[1] as User;

                    RoleName = _Role.Name;

                    CanChange = !((User.AdminInterface_Proxy)_User.Admin).IsNull;
                    IsChecked = (bool)array[2];
                }
            }
            return Task.CompletedTask;
        }
        #endregion

        #region Fields
        private bool _IsChecked;
        public bool IsChecked
        {
            get => _IsChecked;
            set
            {
                SetProperty(ref _IsChecked, value);
                UpdateRoleCommand.Execute(null);
            }
        }

        private bool _CanChange;
        public bool CanChange
        {
            get => _CanChange;
            set
            {
                SetProperty(ref _CanChange, value);
            }
        }

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

        #region Commands
        private ICommand _UpdateRoleCommand;
        public ICommand UpdateRoleCommand
        {
            get => _UpdateRoleCommand;
            set => SetProperty(ref _UpdateRoleCommand, value);
        }
        public async void UpdateRoleCommandExecute()
        {
            if(!CanChange)
            {
                return;
            }

            if(_API.IsConnected && _User != null)
            {
                try
                {
                    List<Role> user_role_list = new List<Role>(await _User.Info.ListRoles().ConfigureAwait(false));
                    if(IsChecked)
                    {
                        if(!user_role_list.Exists(x => string.Equals(x.Name, _Role.Name, StringComparison.Ordinal)))
                        {
                            await _User.Admin.AddRole(_Role).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        if(user_role_list.Exists(x => string.Equals(x.Name, _Role.Name, StringComparison.Ordinal)))
                        {
                            await _User.Admin.RemoveRole(_Role).ConfigureAwait(false);
                        }
                    }
                }
                catch (RpcException exception) when (string.Equals(exception.Message, "RPC connection is broken. Task would never return.", StringComparison.Ordinal))
                {
                    Log.Debug("RPC Connection Loss");
                }
            }       
         }

        public void Dispose()
        {
            _User = null;
            _Role = null;
        }
        #endregion
    }
}
