using Valg.EVA.Skanning.ContainerExtensions;
using Valg.EVA.Skanning.Identity;
using Valg.EVA.Skanning.Resources.Language;
using Valg.EVA.Skanning.UserInterfaceElements.MessageBox;
using System;
using Valg.EVA.Skanning.UserInterfaceElements.LightBox;
using Valg.EVA.Skanning.UserInterfaceElements.Welcome;

namespace Valg.EVA.Skanning.UserInterfaceElements.Login
{
    public class LoginProcessViewModel : ViewModelBase
    {
        private readonly ITypedFactory typedFactory;
        private readonly IIdentityProvider identityProvider;
        private string icon;

        public LoginProcessViewModel(ITypedFactory typedFactory, IIdentityProvider identityProvider)
        {
            this.typedFactory = typedFactory;
            this.identityProvider = identityProvider;
        }

        public LoginResult Login(string applicationAccessClaimValue, string windowIcon, bool showEmergencyModeConfiguration = false)
        {
            icon = windowIcon;
            if (!identityProvider.HasClaim(applicationAccessClaimValue))
            {
                WelcomeResult result = null;

                while (result == null || !result.CanProceedFromWelcomeScreen)
                {
                    var welcomeWindow = typedFactory.Create<WelcomeView>();
                    welcomeWindow.ViewModel.ShowEmergencyModeConfiguration = showEmergencyModeConfiguration;
                    welcomeWindow.ViewModel.WindowIcon = windowIcon;

                    PublishEvent<ShowLightBoxEvent, LightBoxEventArgs>(new LightBoxEventArgs(welcomeWindow));
                    result = welcomeWindow.Result;
                }

                if (result == WelcomeResult.ShowIdPortenLogin)
                {
                    var loginResult = LoginWithIdPorten(applicationAccessClaimValue);
                    return loginResult == LoginResult.Unknown ? Login(applicationAccessClaimValue, windowIcon, showEmergencyModeConfiguration) : loginResult;
                }

                if (result == WelcomeResult.EmergencyModeLoginCompleted)
                {
                    
                    identityProvider.BroadCastSecurityContextHasChanged();
                    return LoginResult.AccessGranted;
                }
            }

            return LoginResult.Unknown;
        }

        private LoginResult LoginWithIdPorten(string applicationAccessClaimValue)
        {
            var loginWindow = typedFactory.Create<LoginWindow>();
            loginWindow.ViewModel.WindowIcon = icon;
            PublishEvent<ShowLightBoxEvent, LightBoxEventArgs>(new LightBoxEventArgs(loginWindow));
            var loginWindowLoginResult = loginWindow.Result;

            if (loginWindowLoginResult == null)
            {
                return LoginResult.Unknown;
            }

            if (loginWindowLoginResult.HasErrors)
            {
                var loginResult = loginWindowLoginResult.IsRootCertificateMissing
                    ? LoginResult.RootCertificateMissingError
                    : LoginResult.HasErrors;

                if (loginWindowLoginResult.Exception != null)
                {
                    ShowErrorMessage(loginWindowLoginResult.Exception);
                }
                else if (loginWindowLoginResult.IsRootCertificateMissing)
                {
                    ShowRootCertificateMissingMessage();
                }
                else
                {
                    ShowErrorMessage();
                }

                return loginResult;
            }
            else
            {
                identityProvider.BroadCastSecurityContextHasChanged();

                LoginResult loginResult = LoginResult.AccessGranted;
                if (!identityProvider.HasClaim(applicationAccessClaimValue))
                {
                    loginResult = LoginResult.AccessDenied;
                    ShowErrorMessage(LanguageString.LoginWindow_NoAccessTitle, LanguageString.LoginWindow_NoAccessMessage, LanguageString.LoginWindow_NoAccessPossibleSolutions);
                }

                return loginResult;
            }
        }

        public void ShowRootCertificateMissingMessage()
        {
            ShowErrorMessage(LanguageString.NoCertificateFoundForLogon, LanguageString.TheSystemCannotFindACertifcateToValidateTheLogin, LanguageString.SolutionsForNoCertificateFoundForLogon);
        }

        public void ShowErrorMessage(Exception exception = null)
        {
            ShowErrorMessage(LanguageString.LoginWindow_Error_Title, LanguageString.LoginWindow_Error_Message, LanguageString.LoginWindow_Error_PossibleSolutions, exception);
        }

        private void ShowErrorMessage(string title, string message, string solutions, Exception exception = null)
        {
            var errorDialog = typedFactory.Create<IMessageBox>();
            errorDialog.Initialize(title, message, solutions, MessageBoxType.Error, exception != null ? new[] { exception } : null);
            PublishEvent<ShowLightBoxEvent, LightBoxEventArgs>(new LightBoxEventArgs(errorDialog as System.Windows.Window));
        }
    }
}
