using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml;
using Prism.Commands;
using Valg.EVA.Skanning.Configuration;
using Valg.EVA.Skanning.Resources.Language;
using Valg.EVA.Skanning.Tools;

namespace Valg.EVA.Skanning.EncryptedConnectionStringConfiguration
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public string DescriptionText => LanguageString.EncryptTool_Description;
        public string DatabaseServerText => LanguageString.EncryptTool_DatabaseServer;
        public string UsernameText => LanguageString.EncryptTool_Username;
        public string PasswordText => LanguageString.EncryptTool_Password;
        public string CancelText => LanguageString.EncryptTool_Cancel;
        public string SaveAndCloseText => LanguageString.EncryptTool_SaveAndClose;
        public string WindowsAuthenticationText => LanguageString.EncryptTool_WindowsAuthentication;
        public string ErrorNotAllRequiredFieldText => LanguageString.EncryptTool_ErrorNotAllFieldsFilledOut;


        public event PropertyChangedEventHandler PropertyChanged;
        public string DatabaseServer { get; set; }
        public string UserName { get; set; }
        public string EncryptedPassword { get; set; }
        public string ConnectionString
        {
            get
            {
                if (IsWindowsAuthenticationChecked)
                {
                    return $@"Data Source={DatabaseServer};Initial Catalog=EvaScanning;Integrated security=true;";
                }
                else
                {
                    return $@"Data Source={DatabaseServer};Initial Catalog=EvaScanning;User Id={UserName};Password={EncryptedPassword}";
                }
            }
        }
        public ICommand SaveConnectionStringCommand => new DelegateCommand(() =>
        {
                if (((String.IsNullOrEmpty(DatabaseServer) || String.IsNullOrEmpty(UserName) || String.IsNullOrEmpty(_passwordBox.Password)) && !IsWindowsAuthenticationChecked) ||
                    (IsWindowsAuthenticationChecked && String.IsNullOrEmpty(DatabaseServer)))
                {
                    OutputText = ErrorNotAllRequiredFieldText;
                    OutputTextColor = Brushes.Red;
                    OnPropertyChanged(nameof(OutputText));
                    OnPropertyChanged(nameof(OutputTextColor));
                }
                else
                {
                    var directory = ConfigurationManager.AppSettings["EvaSkanningInstallationPath"];
                    try
                    {
                        EncryptedPassword = _dataProtectionApi.Encrypt(_passwordBox.Password);
                        foreach (var file in ConfigurationManager.AppSettings["ConnectionStringFiles"].Split(';'))
                        {
                            var fullPath = Path.Combine(directory, file.ToString());
                            SaveConnectionStringToConfigurationFile(fullPath);
                        }

                        _mainWindow.Close();
                    }
                    catch (Exception ex)
                    {
                        OutputText = $"{LanguageString.EncryptTool_UnexpectedError}{Environment.NewLine}{ex.Message}{Environment.NewLine}{ex.StackTrace}";
                        OutputTextColor = Brushes.Red;
                        OnPropertyChanged(nameof(OutputText));
                        OnPropertyChanged(nameof(OutputTextColor));
                    }

                }


        });

        private void SaveConnectionStringToConfigurationFile(string fullPath)
        {
            if (File.Exists(fullPath))
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.Load(fullPath);
                var node = xmlDoc.SelectSingleNode("//configuration/connectionStrings/add[@name='ScanningDatabase']/@connectionString");
                if (node != null)
                {
                    node.Value = ConnectionString;
                }

                xmlDoc.Save(fullPath);
            }
        }

        public ICommand CancelCommand => new DelegateCommand(() =>
        {
            _mainWindow.Close();
        });
        public string OutputText { get; set; }
        public SolidColorBrush OutputTextColor { get; set; }
        public bool IsWindowsAuthenticationChecked
        {
            get => _isWindowsAuthenticationChecked;
            set
            {
                _isWindowsAuthenticationChecked = value;
                OnPropertyChanged(nameof(IsWindowsAuthenticationChecked));
                OnPropertyChanged(nameof(IsSqlAuthenticationEnabled));
            }
        }

        public bool IsSqlAuthenticationEnabled => !IsWindowsAuthenticationChecked;
        public bool IsSaveButtonEnabled { get; set; } = true;


        private readonly PasswordBox _passwordBox = null;
        private readonly MainWindow _mainWindow = null;
        private readonly DataProtectionApi _dataProtectionApi = new DataProtectionApi();
        private bool _isWindowsAuthenticationChecked;

        private bool CheckDirectoryAndConfigFilesExists()
        {
            bool result = true;
            var directory = ConfigurationManager.AppSettings["EvaSkanningInstallationPath"];
            if (!Directory.Exists(directory))
            {
                OutputText = String.Empty;
                OutputTextColor = Brushes.Red;
                OutputText += LanguageString.EncryptTool_EvaSkanningNotInstalled + Environment.NewLine;
                IsSaveButtonEnabled = false;
                result = false;
            }
            foreach (var file in ConfigurationManager.AppSettings["ConnectionStringFiles"].Split(';'))
            {
                var fullPath = Path.Combine(directory, file);
                if (!File.Exists(fullPath))
                {
                    OutputTextColor = Brushes.Red;
                    OutputText += LanguageString.EncryptTool_MissingConfigution + " " + file + Environment.NewLine;
                    IsSaveButtonEnabled = false;
                    result = false;
                }
            }
            OnPropertyChanged(nameof(OutputText));
            OnPropertyChanged(nameof(OutputTextColor));
            OnPropertyChanged(nameof(IsSaveButtonEnabled));
            return result;
        }

        public MainWindowViewModel(MainWindow mainWindow, System.Windows.Controls.PasswordBox passwordBox)
        {
            _passwordBox = passwordBox;
            _mainWindow = mainWindow;

            if (CheckDirectoryAndConfigFilesExists())
            {
                var configuration = ReadApplicationConfiguration();
                if (configuration != null)
                {
                    var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(configuration.ConnectionString);
                    if (sqlConnectionStringBuilder.IntegratedSecurity)
                    {
                        DatabaseServer = configuration.DatabaseServerName;
                        IsWindowsAuthenticationChecked = true;
                    }
                    else
                    {
                        DatabaseServer = configuration.DatabaseServerName;
                        UserName = sqlConnectionStringBuilder.UserID;
                    }
                }
            }
        }

        private EncryptedDatabaseConfiguration ReadApplicationConfiguration()
        {
            var firstConfigFile = Path.Combine(ConfigurationManager.AppSettings["EvaSkanningInstallationPath"],
                ConfigurationManager.AppSettings["ConnectionStringFiles"].Split(';').FirstOrDefault() ?? String.Empty);
            if (!String.IsNullOrEmpty(firstConfigFile))
            {
                var applicationReader = new ApplicationConfigurationReader(new ConfigurationFileProvider(firstConfigFile));
                return new EncryptedDatabaseConfiguration(applicationReader);
            }

            return null;
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

