using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using ChatController.Annotations;
using ChatController.HauptKlassen;
using ChatController.LoginKlassen;
using ChatController.Utilities;
using ChatController.Utilities.Extensions;
using Cursors = System.Windows.Input.Cursors;
using MessageBox = System.Windows.MessageBox;
using Path = System.IO.Path;

namespace ChatController
{
    public partial class LoginControl : INotifyPropertyChanged
    {
        private ChatControlWaitLayer _WaitLayer;

        public string UserName
        {
            get => _Benutzername;

            set
            {
                if (!Equals(_Benutzername, value))
                {
                    _Benutzername = value;
                    OnPropertyChanged(nameof(UserName));
                }
            }
        }

        public string Password
        {
            get => PasswordBox.Password;

            set => PasswordBox.Password = value;
        }

        public string ChatCode
        {
            get => _ChatCode;

            set
            {
                if(!Equals(_ChatCode, value))
                {
                    _ChatCode = value;
                    OnPropertyChanged(nameof(ChatCode));
                }
            }
        }

        public string Tenant
        {
            get => _Kundennummer;

            set
            {
                if(!Equals(_Kundennummer, value))
                {
                    _Kundennummer = value;
                    OnPropertyChanged(nameof(Tenant));
                }
            }
        }

        public delegate void LoginDelegate(ChatDatenUebergabe cdu);

        public event LoginDelegate OnLogin;

        private string _Benutzername       = string.Empty;
        private string _ChatCode           = string.Empty;
        private string _Kundennummer       = string.Empty;
        private readonly string _Version       = "1.6";

        public string Version => $"Version: {_Version}";

        public LoginControl()
        {
            InitializeComponent();

            DataContext = this;

            LeseDateiFallsVorhanden();
        }

        private void AnmeldenButton_OnClick(object sender, RoutedEventArgs e)
        {
            Anmelden();
        }

        private void StartWaiting()
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) StartWaitingImmediately);
        }

        private void StartWaitingImmediately()
        {
            if (_WaitLayer == null)
            {
                _WaitLayer = new ChatControlWaitLayer();
                Panel.SetZIndex(_WaitLayer, int.MaxValue);
                RootGrid.Children.Add(_WaitLayer);
                _WaitLayer.RefreshUI();
            }
        }

        private void EndWaiting()
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action) delegate
            {
                if (_WaitLayer != null)
                {
                    RootGrid.Children.Remove(_WaitLayer);
                    _WaitLayer = null;
                }
            });
        }

        private void Anmelden()
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(_Kundennummer) && !string.IsNullOrWhiteSpace(_ChatCode) && !string.IsNullOrWhiteSpace(_Benutzername) && Password.Length > 0)
                {
                    StartWaiting();

                    var login = new Login(_Kundennummer, _ChatCode, _Benutzername, PasswordBox.Password);

                    login.DoLoginAsync(chatDatenUebergabe =>
                    {
                        this.Dispatch(() =>
                        {
                            EndWaiting();

                            if(chatDatenUebergabe != null)
                            {
                                AutosetDaten();

                                OnLogin?.Invoke(chatDatenUebergabe);
                            }
                        });
                    },
                        errorMessage =>
                        {
                            this.Dispatch(() =>
                            {
                                EndWaiting();

                                MessageBox.Show(errorMessage, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                            });
                        });
                }
                else
                {
                    MessageBox.Show("Bitte alle Felder ausfüllen!", "Info", MessageBoxButton.OK);
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show("Fehler: " + exception.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
                EndWaiting();
                Cursor = Cursors.Arrow;
            }
        }

        private void LoadTenantAndChatCodeFromFile()
        {
            try
            {
                if(File.Exists(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName)))
                {
                    var lines = new List<string>();
                    using(var streamReader = new StreamReader(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName), true))
                    {
                        string line;

                        while((line = streamReader.ReadLine()) != null)
                        {
                            var encodedTextBytes = Convert.FromBase64String(line);

                            var plainText = Encoding.UTF8.GetString(encodedTextBytes);

                            lines.Add(plainText);
                        }
                    }

                    if(lines.Count == 2)
                    {
                        _Kundennummer = lines[0];
                        _ChatCode = lines[1];
                    }
                }
            }
            catch(Exception e)
            {
                MessageBox.Show("Fehler: \n" + e.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LeseDateiFallsVorhanden()
        {
            LoadTenantAndChatCodeFromFile();
        }

        private void AutosetDaten()
        {
            try
            {
                if(File.Exists(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName)))
                {
                    File.SetAttributes(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName), FileAttributes.Normal);
                    File.Delete(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName));
                }

                using(var streamWriter = new StreamWriter(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName)))
                {
                    Encoding utf8Encoding = new UTF8Encoding();
                    var tenantBytes = utf8Encoding.GetBytes(_Kundennummer);
                    var encodedTenant = Convert.ToBase64String(tenantBytes);

                    var chatCodeBytes = utf8Encoding.GetBytes(_ChatCode);
                    var encodedChatCode = Convert.ToBase64String(chatCodeBytes);

                    streamWriter.WriteLine(encodedTenant);
                    streamWriter.WriteLine(encodedChatCode);

                    File.SetAttributes(Path.Combine(GetAndCreateUserAppDataPath(), Constants.TenantAndChatCodeFileName), FileAttributes.ReadOnly);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Fehler: \n" + e.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private static string GetAndCreateUserAppDataPath()
        {
            try
            {
                var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                var companyFilePath = Path.Combine(localAppData, "beyondSoft");

                if (!Directory.Exists(companyFilePath))
                {
                    Directory.CreateDirectory(companyFilePath);
                }

                var bewoFilePath = Path.Combine(companyFilePath, "OwnChat");

                if (!Directory.Exists(bewoFilePath))
                {
                    Directory.CreateDirectory(bewoFilePath);
                }

                return bewoFilePath;
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Fehler beim Anlegen des Anwendungsordners. Sie besitzen nicht die erforderlichen Rechte, bitte wenden Sie sich an Ihren Systemadministrator.\n" +
                    ex.Message, "BeWoPlaner", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
            return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        }

        public void Login()
        {
            Anmelden();
        }

        public event PropertyChangedEventHandler PropertyChanged;

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