using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using C4IT.MultiLanguage;
using C4IT.FASD.Base;

using FasdDesktopUi.Basics.Models;
using C4IT.FASD.Cockpit.Communication;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Pages.M42AuthenticationPage;
using FasdDesktopUi.Pages.DetailsPage;
using System.ComponentModel;
using System.Globalization;
using System.Diagnostics.Eventing.Reader;

namespace FasdDesktopUi.Pages.SettingsPage
{
    public partial class M42SettingsPageView : SettingsPageBase
    {
        private static M42SettingsPageView _Instance = null;

        public static M42SettingsPageView Instance
        {
            get
            {
                return _Instance ?? (_Instance = new M42SettingsPageView());
            }
        }

        private double borderWidth = double.MaxValue;

        private enumM42AuthenticationMethod authenticationMethod;

        private enumM42AuthenticationControl authenticationControl;

        private bool formsAuthenticated = false;

        private bool IsTemporaryDisabled = false;

        private bool _isMethodBlurred = false;
        public bool IsNotMethodBlurred
        {
            get { return !_isMethodBlurred; }
        }
        public bool IsMethodBlurred
        {
            get { return _isMethodBlurred; }
            set
            {
                if (value != _isMethodBlurred)
                {
                    _isMethodBlurred = value;
                    OnPropertyChanged(nameof(IsMethodBlurred));
                    OnPropertyChanged(nameof(IsNotMethodBlurred));
                }
            }
        }

        private bool _isMethodAuto = false;
        public bool IsNotMethodAuto { get { return !_isMethodAuto; } }
        public bool IsMethodAuto
        {
            get { return _isMethodAuto; }
            set
            {
                if (value != _isMethodAuto)
                {
                    _isMethodAuto = value;
                    OnPropertyChanged(nameof(IsMethodAuto));
                    OnPropertyChanged(nameof(IsNotMethodAuto));
                }
            }
        }


        private M42SettingsPageView()
        {
            InitializeComponent();
        }

        private void M42SettingsWindows_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (e.NewValue is bool isVisible)
                {
                    if (isVisible && !IsTemporaryDisabled)
                    {
                        App.HideAllSettingViews();

                        if (this.IsLoaded)
                            InitializeControlValues();
                    }
                }

                BlurInvoker_IsActiveChanged(sender, e);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #region DialogButton_Click

        public void DialogButton_Click(object sender)
        {
            if (!(sender is FrameworkElement senderElement))
                return;

            if (!(senderElement.Tag is bool tagValue))
                return;

            if (tagValue)
            {
            }

            Close();

            if (tagValue)
            {
                var _h = Dispatcher.Invoke(async () =>
                {
                    await Task.Delay(300);

                    var dialogResult = CustomMessageBox.CustomMessageBox.Show(cMultiLanguageSupport.GetItem("M42Settings.ChangedInfoDialog.Text"), cMultiLanguageSupport.GetItem("M42Settings.RestartDialog.Caption"), enumHealthCardStateLevel.Info, null, true);

                    if (dialogResult == true)
                    {
                        System.Windows.Forms.Application.Restart();
                        Application.Current.Shutdown();
                    }
                });
            }
        }

        #endregion

        #region CloseButton_Click

        private void CloseButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Close();
        }

        private void CloseButton_TouchDown(object sender, TouchEventArgs e)
        {
            Close();
        }

        #endregion

        private async void M42SettingsWindows_Loaded(object sender, RoutedEventArgs e)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                // initialize the window title
                var _ServerDisplayName = cCockpitConfiguration.Instance?.m42ServerConfiguration?.DisplayName;
                if (!string.IsNullOrEmpty(_ServerDisplayName))
                {
                    var _strTitle = cMultiLanguageSupport.GetItem("M42Settings.Header");
                    _strTitle = string.Format(_strTitle, _ServerDisplayName);
                    txtHeader.Text = _strTitle;
                }

                // get the current logon user info
                var _currUserInfo = await cFasdCockpitCommunicationBase.Instance.GetAdditionalUserInfo(enumAdditionalAuthentication.M42WinLogon);
                if (_currUserInfo != null)
                {
                    var _txt = cMultiLanguageSupport.GetItem("M42Settings.LogonMethod.CurrentUserValid");
                    var _ci = new CultureInfo(cMultiLanguageSupport.CurrentLanguage);
                    var _dt = _currUserInfo.ValidUntil.ToLocalTime().ToString(_ci);
                    _txt = string.Format(_txt, _currUserInfo.Name, _dt);
                    txtCurrentUser.Text = _txt;
                }
                else
                {
                    txtCurrentUser.Text = cMultiLanguageSupport.GetItem("M42Settings.LogonMethod.CurrentUserInvalid");
                }

                // get user name for passthrough label
                string userName;
                string userAccount;
                lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
                {
                    userName = cFasdCockpitCommunicationBase.CockpitUserInfo?.Name;
                    userAccount = cFasdCockpitCommunicationBase.CockpitUserInfo?.AdAccount;
                }
                string str = null;
                if (string.IsNullOrEmpty(userName))
                {
                    if (!string.IsNullOrEmpty(userAccount))
                        str = userAccount;
                }
                else
                {
                    if (string.IsNullOrEmpty(userAccount))
                        str = userName;
                    else
                        str = $"{userName}({userAccount})";
                }


                if (str != null)
                {
                    var s = cMultiLanguageSupport.GetItem("M42Settings.LogonMethod.PassthoughUser");
                    str = string.Format(s, str);
                    labelPassthough.Text = str;
                }

                txtAuthenticationError.Visibility = Visibility.Hidden;

                InitializeControlValues();

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

        }

        private void InitializeControlValues()
        {
            // set the initial input control values
            BasicUserName.Text = cFasdCockpitConfig.Instance?.M42Config?.BasicUser ?? "";

            var _pw = PrivateSecurePassword.Instance.Decode(cFasdCockpitConfig.Instance?.M42Config.BasicPassword) ?? "";
            pwBoxPasswordBasicShow.Password = _pw;

            _pw = PrivateSecurePassword.Instance.Decode(cFasdCockpitConfig.Instance?.M42Config.ApiToken) ?? "";
            pwBoxPasswordTokenShow.Password = _pw;

            txtBoxPasswordBasicShow.Text = pwBoxPasswordBasicShow?.Password;
            txtBoxPasswordTokenShow.Text = pwBoxPasswordTokenShow?.Password;

            // set the initial radio button values
            switch (cFasdCockpitConfig.Instance?.M42Config?.Control)
            {
                case enumM42AuthenticationControl.always:
                    radioButtonLogonActiveYes.IsChecked = true;
                    break;
                case enumM42AuthenticationControl.never:
                    radioButtonLogonActiveNo.IsChecked = true;
                    break;
                default:
                    radioButtonLogonActiveAuto.IsChecked = true;
                    break;
            }

            authenticationMethod = cFasdCockpitConfig.Instance?.M42Config?.Method ?? enumM42AuthenticationMethod.passthrough;
            switch (cFasdCockpitConfig.Instance?.M42Config?.Method)
            {
                case enumM42AuthenticationMethod.basic:
                    radioButtonLogonMethodBasic.IsChecked = true;
                    break;
                case enumM42AuthenticationMethod.token:
                    radioButtonLogonMethodToken.IsChecked = true;
                    break;
                case enumM42AuthenticationMethod.forms:
                    radioButtonLogonMethodForms.IsChecked = true;
                    break;
                default:
                    radioButtonLogonMethodPassthrough.IsChecked = true;
                    break;
            }
            LogonActiveChanged();
        }

        private void logonMethodChanged()
        {
            if (radioButtonLogonMethodBasic.IsChecked == true)
            {
                authenticationMethod = enumM42AuthenticationMethod.basic;
                additionalBlockLogonMethodBasic.Visibility = Visibility.Visible;
                additionalBlockLogonMethodToken.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodForms.Visibility = Visibility.Collapsed;
            }
            else if (radioButtonLogonMethodToken.IsChecked == true)
            {
                authenticationMethod = enumM42AuthenticationMethod.token;
                additionalBlockLogonMethodBasic.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodToken.Visibility = Visibility.Visible;
                additionalBlockLogonMethodForms.Visibility = Visibility.Collapsed;
            }
            else if (radioButtonLogonMethodForms.IsChecked == true)
            {
                authenticationMethod = enumM42AuthenticationMethod.forms;
                additionalBlockLogonMethodBasic.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodToken.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodForms.Visibility = Visibility.Visible;
            }
            else
            {
                authenticationMethod = enumM42AuthenticationMethod.passthrough;
                additionalBlockLogonMethodBasic.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodToken.Visibility = Visibility.Collapsed;
                additionalBlockLogonMethodForms.Visibility = Visibility.Collapsed;
            }
        }

        private void radioButtonLogonMethod_Checked(object sender, RoutedEventArgs e)
        {
            logonMethodChanged();
        }

        private void LogonActiveChanged()
        {
            if (radioButtonLogonActiveNo.IsChecked == true)
            {
                authenticationControl = enumM42AuthenticationControl.never;
                IsMethodBlurred = true;
                IsMethodAuto = false;
            }
            else if (radioButtonLogonActiveYes.IsChecked == true)
            {
                authenticationControl = enumM42AuthenticationControl.always;
                IsMethodBlurred = false;
                IsMethodAuto = false;
            }
            else
            {
                authenticationControl = enumM42AuthenticationControl.auto;
                IsMethodBlurred = false;
                IsMethodAuto = true;
                radioButtonLogonMethodPassthrough.IsChecked = true;
            }

        }

        private void radioButtonLogonActive_Checked(object sender, RoutedEventArgs e)
        {
            LogonActiveChanged();
        }

        private void borderLogon_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var _w = e.NewSize.Width;
            if (_w < borderWidth)
            {
                borderWidth = _w;
                additionalBlockLogonMethodBasic.MaxWidth = _w;
                additionalBlockLogonMethodForms.MaxWidth = _w;
                additionalBlockLogonMethodToken.MaxWidth = _w;
            }
        }

        private void pwBoxPasswordBasicShow_PasswordChanged(object sender, RoutedEventArgs e)
        {
            if (txtBoxPasswordBasicShow != null && txtBoxPasswordBasicShow.Visibility != Visibility.Visible)
                txtBoxPasswordBasicShow.Text = pwBoxPasswordBasicShow?.Password;
        }

        private void txtBoxPasswordBasicShow_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (pwBoxPasswordBasicShow != null && pwBoxPasswordBasicShow.Visibility != Visibility.Visible)
                pwBoxPasswordBasicShow.Password = txtBoxPasswordBasicShow?.Text;
        }

        private void pwBoxPasswordTokenShow_PasswordChanged(object sender, RoutedEventArgs e)
        {
            if (txtBoxPasswordTokenShow != null && txtBoxPasswordTokenShow.Visibility != Visibility.Visible)
                txtBoxPasswordTokenShow.Text = pwBoxPasswordTokenShow?.Password;
        }

        private void pwBoxPasswordTokenHide_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (pwBoxPasswordTokenShow != null && pwBoxPasswordTokenShow.Visibility != Visibility.Visible)
                pwBoxPasswordTokenShow.Password = txtBoxPasswordBasicShow?.Text;
        }

        private void iconPasswordShow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is FrameworkElement _fr))
                return;

            switch (_fr.Tag.ToString())
            {
                case "PwBasicOn":
                    iconPasswordBasicHide.Visibility = Visibility.Visible;
                    iconPasswordBasicShow.Visibility = Visibility.Collapsed;
                    txtBoxPasswordBasicShow.Visibility = Visibility.Visible;
                    pwBoxPasswordBasicShow.Visibility = Visibility.Collapsed;
                    return;
                case "PwBasicOff":
                    iconPasswordBasicShow.Visibility = Visibility.Visible;
                    iconPasswordBasicHide.Visibility = Visibility.Collapsed;
                    pwBoxPasswordBasicShow.Visibility = Visibility.Visible;
                    txtBoxPasswordBasicShow.Visibility = Visibility.Collapsed;
                    return;
                case "TokenOn":
                    iconTokenHide.Visibility = Visibility.Visible;
                    iconTokenShow.Visibility = Visibility.Collapsed;
                    txtBoxPasswordTokenShow.Visibility = Visibility.Visible;
                    pwBoxPasswordTokenShow.Visibility = Visibility.Collapsed;
                    return;
                case "TokenOff":
                    iconTokenShow.Visibility = Visibility.Visible;
                    iconTokenHide.Visibility = Visibility.Collapsed;
                    pwBoxPasswordTokenShow.Visibility = Visibility.Visible;
                    txtBoxPasswordTokenShow.Visibility = Visibility.Collapsed;
                    return;
            }
        }

        private void ConfirmButton_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ConfirmButton_Click(sender);
        }

        private void ConfirmButton_TouchDown(object sender, TouchEventArgs e)
        {
            ConfirmButton_Click(sender);
        }

        private async void ConfirmButton_Click(object sender)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                this.IsEnabled = false;
                Mouse.OverrideCursor = Cursors.Wait;

                cFasdCockpitConfig.Instance.M42Config.Control = authenticationControl;
                cFasdCockpitConfig.Instance.Save("M42Config\\Control");

                if (authenticationControl == enumM42AuthenticationControl.never)
                {
                    Close();
                    return;
                }

                bool isAuthenticated = false;
                cF4sdCockpitM42BearerTokenInfo TokenInfo = null;
                bool HasChanged = false;
                HasChanged |= authenticationMethod != cFasdCockpitConfig.Instance.M42Config.Method;
                switch (authenticationMethod)
                {
                    case enumM42AuthenticationMethod.passthrough:
                        TokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonPassthrough();
                        if (TokenInfo?.Token != null)
                            isAuthenticated = true;
                        break;
                    case enumM42AuthenticationMethod.basic:
                        var _user = BasicUserName.Text;
                        var _pw = pwBoxPasswordBasicShow.Password;
                        HasChanged |= _user != cFasdCockpitConfig.Instance.M42Config.BasicUser;
                        HasChanged |= PrivateSecurePassword.Instance.Decode(cFasdCockpitConfig.Instance.M42Config.BasicPassword) != _pw;
                        TokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonBasic(_user, _pw);
                        if (TokenInfo?.Token != null)
                        {
                            isAuthenticated = true;
                            if (HasChanged)
                            {
                                cFasdCockpitConfig.Instance.M42Config.BasicUser = _user;
                                cFasdCockpitConfig.Instance.M42Config.BasicPassword = PrivateSecurePassword.Instance.Encode(_pw);
                                cFasdCockpitConfig.Instance.Save("M42Config\\BasicUser");
                                cFasdCockpitConfig.Instance.Save("M42Config\\BasicPassword");
                            }
                        }
                        break;
                    case enumM42AuthenticationMethod.token:
                        var _token = pwBoxPasswordTokenShow.Password;
                        HasChanged |= PrivateSecurePassword.Instance.Decode(cFasdCockpitConfig.Instance.M42Config.ApiToken) != _token;
                        TokenInfo = await cFasdCockpitCommunicationBase.Instance.M42.ValidateLogonToken(_token);
                        if (TokenInfo?.Token != null)
                        {
                            isAuthenticated = true;
                            if (HasChanged)
                            {
                                cFasdCockpitConfig.Instance.M42Config.ApiToken = PrivateSecurePassword.Instance.Encode(_token);
                                cFasdCockpitConfig.Instance.Save("M42Config\\ApiToken");
                            }
                        }
                        break;
                    case enumM42AuthenticationMethod.forms:
                        if (formsAuthenticated)
                            isAuthenticated = true;
                        break;
                }

                if (isAuthenticated)
                {
                    cFasdCockpitConfig.Instance.M42Config.Method = authenticationMethod;
                    cFasdCockpitConfig.Instance.Save("M42Config\\Method");

                    txtAuthenticationError.Visibility = Visibility.Hidden;
                    if (HasChanged)
                    {
                        var _tsk = Dispatcher.Invoke(async () =>
                        {
                            await Task.Delay(100);

                            var dialogResult = CustomMessageBox.CustomMessageBox.Show(cMultiLanguageSupport.GetItem("M42Settings.ChangedInfoDialog.Text"), cMultiLanguageSupport.GetItem("M42Settings.RestartDialog.Caption"), enumHealthCardStateLevel.Info, null, true);

                            if (dialogResult == true)
                            {
                                System.Windows.Forms.Application.Restart();
                                Application.Current.Shutdown();
                            }
                        });
                    }

                    Close();
                }
                else
                {
                    txtAuthenticationError.Visibility = Visibility.Visible;
                }
                  

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                Mouse.OverrideCursor = null; ;
                this.IsEnabled = true;
                LogMethodEnd(CM);
            }

        }

        private void DoFormsAuthentication_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (cFasdCockpitCommunicationBase.CockpitUserInfo == null)
                    return;

                IsTemporaryDisabled = true;
                this.IsEnabled = false;

                var logonPage = new F4sdM42FormsAuthentication(Reauthenticate: false);
                var _ret = logonPage.ShowDialog();
                logonPage = null;

                if (_ret == true)
                {
                    formsAuthenticated = true;
                    txtAuthenticationError.Visibility = Visibility.Hidden;
                }

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                this.IsEnabled = true;
                IsTemporaryDisabled = false;
                LogMethodEnd(CM);
            }
        }

        private void M42SettingsWindows_Closed(object sender, EventArgs e)
        {
            _Instance = null;
        }

    }
}
