using System.Linq;
using Valg.EVA.Skanning.Identity;
using Valg.EVA.Skanning.Services.SystemServices;
using System;
using System.Diagnostics;
using Valg.EVA.Skanning.Contracts;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.Signing;

namespace Valg.EVA.Skanning.UserInterfaceElements.Login
{
    public class LoginWindowViewModel : ViewModelBase, ILoginWindowViewModel
    {
        private readonly IPemSignatureValidator pemSignatureValidator;
        private readonly IIdentityProvider identityProvider;
        private readonly ISystemService systemService;
        private readonly IExternalEndpointsConfiguration externalEndpointsConfiguration;
        private LoginWindowLoginResult loginResult;
        private readonly IClaimsAndRolesBuilder claimsAndRolesBuilder;
        private bool showLoginBox;
        private bool showErrorBox;
        private string windowIcon;

        public LoginWindowViewModel(IClaimsAndRolesBuilder claimsAndRolesBuilder, IPemSignatureValidator pemSignatureValidator, IIdentityProvider identityProvider, 
            ISystemService systemService, IExternalEndpointsConfiguration externalEndpointsConfiguration)
        {
            this.pemSignatureValidator = pemSignatureValidator;
            this.identityProvider = identityProvider;
            this.systemService = systemService;
            this.externalEndpointsConfiguration = externalEndpointsConfiguration;
            this.claimsAndRolesBuilder = claimsAndRolesBuilder;
            ShowLoginBox = true;
        }

        public Uri LogonStartUrl => new Uri(externalEndpointsConfiguration.LogonStartUrl);

        public Uri LogonCompleteUrl => new Uri(externalEndpointsConfiguration.LogonCompleteUrl);

        public bool CloseLoginWindow { get; private set; }

        public bool ShowLoginBox
        {
            get
            {
                return showLoginBox;
            }
            private set
            {
                showLoginBox = value;
                OnPropertyChanged();
            }
        }

        public bool ShowErrorBox
        {
            get 
            {
                return showErrorBox;
            }
            private set
            {
                showErrorBox = value;
                OnPropertyChanged();
            }
        }

        public void ShowErrorInformation()
        {
            ShowErrorBox = true;
            ShowLoginBox = false;
        }

        public LoginWindowLoginResult Result => loginResult;
        public string WindowIcon
        {
            get
            {
                return windowIcon;
            }
            set
            {
                windowIcon = value;
                OnPropertyChanged();
            }
        }

        public void PageLoaded(Uri uri, IHtmlDocument document)
        {
            if (IsOnRequestedUrl(uri))
            {
                string hostProcess = Process.GetCurrentProcess().ProcessName;

                try
                {
                    byte[] token = Convert.FromBase64String(document.GetToken());
                    byte[] signature = Convert.FromBase64String(document.GetSignature());

                    var result = pemSignatureValidator.ValidateDocumentSignature(token, signature);

                    if (!result.IsRootCertificateMissing && result.IsValid)
                    {
                        claimsAndRolesBuilder.ParseToken(token, signature);
                        loginResult = LoginWindowLoginResult.LoginFromIdPorten;
                    }
                    else
                    {
                        loginResult = LoginWindowLoginResult.ErrorInToken;
                    }

                    if (identityProvider.Roles.Count > 0)
                    {
                        systemService.InitElectionConfigDataCache(identityProvider.Roles.First().Area.ElectionEventId);
                    }
                }
                catch (Exception e)
                {
                    if (loginResult == null)
                    {
                        loginResult = LoginWindowLoginResult.CreateResultWithError(e);
                    }

                    EvaSkanningEventSource.Log.ErrorWhileLoggingIn(hostProcess, e.ToString(), LogonCompleteUrl.ToString());
                }
                finally
                {
                    CloseLoginWindow = true;
                }
            }
            else
            {
                CloseLoginWindow = false;
            }
        }

        private bool IsOnRequestedUrl(Uri uri)
        {
            return LogonCompleteUrl.GetLeftPart(UriPartial.Path) == uri.GetLeftPart(UriPartial.Path);
        }
    }
}
