using I18N;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
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.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace ApoIdentStartSettings
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string DEACTIVATED_MODE = "Deactivated";

        public MainWindow()
        {
            try
            {
                string file = Assembly.GetExecutingAssembly().Location;
                Catalog.Init(System.IO.Path.GetDirectoryName(file));

                InitializeComponent();

                if (Catalog.Locale != "de")
                    this.HelpMenu.Visibility = Visibility.Collapsed;

                this.MainWin.Title = Catalog.GetString("Apo-Ident Start Settings");
                this.OkButtonLabel.Content = Catalog.GetString("OK");
                this.ProfileLabel.Content = Catalog.GetString("Profile name:");
                this.TitleLabel.Content = Catalog.GetString("Please select the Windows User Profile to start Apo-Ident.");

                this.InfoMenu.Header = Catalog.GetString("_Info");
                this.LicenseMenuItem.Header = Catalog.GetString("License");

                this.HelpMenu.Header = Catalog.GetString("_Help");
                this.ManualMenuItem.Header = Catalog.GetString("Manual");

                List<string> start_item = new List<string>();           
                start_item.Add(Catalog.GetString("Loading ..."));
                this.accounts_combobox.ItemsSource = start_item;
                this.accounts_combobox.SelectedIndex = 0;
                this.MainWin.IsEnabled = false;

                this.CheckAdminRights();
                this.CheckInstallation();
               Thread thread = new Thread(this.SetExecutionProfileToCombobox);
                thread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format(Catalog.GetString("An unknown error occurred: {0}"), ex.Message));
                Application.Current.MainWindow.Close();
                Environment.Exit(3);
            }
        }

        private void CheckAdminRights()
        {
            System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
            System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity);
            if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator) == false)
            {
                MessageBox.Show(Catalog.GetString("You need administration rights to execute this application. Please start the program with the needed rights."));
                Application.Current.MainWindow.Close();
                Environment.Exit(1);
            }
        }

        private void CheckInstallation()
        {
            string qs_version = this.CurrentQSVersion;

            Version current_version = null;
            if (qs_version != null)
                current_version = new Version(qs_version.Split(' ')[1]);

            if (qs_version == null || current_version < new Version("2.0"))
            {
                MessageBox.Show(Catalog.GetString("Please check, that 'QuickStep Apo-Ident 2.0' or higher is installed"));
                Application.Current.MainWindow.Close();
                Environment.Exit(2);
            }
        }


        private void SetExecutionProfileToCombobox()
        {
            List<string> all_users = null;
            Exception e = null;
            try
            {
               all_users = this.AllUsers;
            }
            catch (Exception ex)
            {
                e = ex;
            }

            this.Dispatcher.Invoke(() =>
            {
                if (all_users == null)
                {
                    Application.Current.MainWindow.Close();
                    MessageBox.Show(String.Format(Catalog.GetString("Could not find any user: {0}"), e.Message));
                    Environment.Exit(4);
                }
                else
                {
                    string current_user = this.ExecutionProfile;
                    this.accounts_combobox.ItemsSource = all_users;

                    this.accounts_combobox.SelectedIndex = 0;

                    if (all_users.Contains(current_user))
                        this.accounts_combobox.SelectedValue = current_user;

                    this.MainWin.IsEnabled = true;
                }
            });
        }

        private Microsoft.Win32.RegistryKey OpenHiperscanKey(bool write)
        {
            Microsoft.Win32.RegistryKey hiperscan = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("HiperScan", write);
            if (hiperscan == null)
            {
                hiperscan = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("WOW6432Node").OpenSubKey("HiperScan", write);
                if (hiperscan == null)
                {
                    return null;
                }
            }

            return hiperscan;
        }

        private string ExecutionProfile
        {
            get
            {
                Microsoft.Win32.RegistryKey hiperscan = this.OpenHiperscanKey(false);
                if (hiperscan == null)
                    return MainWindow.DEACTIVATED_MODE;

                return (string)hiperscan.GetValue("QuickStepExecutionProfile");
            }
        }

        private List<string> AllUsers
        {
            get
            {
                List<string> account_names = new List<string>();

                ManagementObjectSearcher usersSearcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_UserAccount");
                ManagementObjectCollection users = usersSearcher.Get();

                var local_users = users.Cast<ManagementObject>().Where(
                    u => (bool)u["Disabled"] == false);

                foreach (ManagementObject user in local_users)
                {
                    string account_name = String.Format("{0}\\{1}",
                        user["Domain"], user["Name"]);

                    account_names.Add(account_name);
                }

                account_names.Sort();
                account_names.Insert(0, Catalog.GetString("Current user"));
                return account_names;
            }
        }

        private string CurrentQSVersion
        {
            get
            {
                Microsoft.Win32.RegistryKey hiperscan = this.OpenHiperscanKey(false);
                if (hiperscan == null)
                    return null;

                hiperscan = hiperscan.OpenSubKey("CurrentQSVersion");
                if (hiperscan == null)
                    return null;

                return (string)hiperscan.GetValue("VersionKey");
            }
        }

        private void OnOkButtonClicked(object sender, RoutedEventArgs e)
        {
            try
            {
                string value = this.accounts_combobox.SelectedIndex == 0 ? MainWindow.DEACTIVATED_MODE : (string)this.accounts_combobox.SelectedValue;

                Microsoft.Win32.RegistryKey hiperscan = this.OpenHiperscanKey(true);
                hiperscan.SetValue("QuickStepExecutionProfile", value);
                Application.Current.MainWindow.Close();
            }
            catch (Exception ex)
            {
                Application.Current.MainWindow.Close();
                MessageBox.Show(String.Format(Catalog.GetString("Error while writing registry: {0}"), ex.Message));
            }
            Environment.Exit(0);
        }

        private void OnLicenseMenuItemClicked(object sender, RoutedEventArgs e)
        {
            LicenseDialog dialog = new LicenseDialog();
            dialog.ShowDialog();
        }

        private void OnManualMenuItemClicked(object sender, RoutedEventArgs e)
        {
            try
            {
                string resource = String.Format("ApoIdentStartSettings.pdf.SumatraPDF.exe");
                string pdf_executable = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "pdf_tmp.exe");
                if (File.Exists(pdf_executable) == false)
                {
                    using (System.IO.Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
                    {
                        using (FileStream file_stream = new FileStream(pdf_executable, FileMode.OpenOrCreate))
                        {
                            int cnt = 0;
                            byte[] buffer = new byte[4096];

                            while ((cnt = stream.Read(buffer, 0, 4096)) != 0)
                                file_stream.Write(buffer, 0, cnt);
                        }
                    }
                }

                resource = String.Format("ApoIdentStartSettings.i18n.manual_{0}.pdf", Catalog.Locale);
                string pdf_file = System.IO.Path.Combine(System.IO.Path.GetTempPath(), String.Format("aiss_{0}.pdf", Catalog.Locale));
                if (File.Exists(pdf_file) == false)
                {
                    using (System.IO.Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
                    {
                        using (FileStream file_stream = new FileStream(pdf_file, FileMode.OpenOrCreate))
                        {
                            int cnt = 0;
                            byte[] buffer = new byte[4096];

                            while ((cnt = stream.Read(buffer, 0, 4096)) != 0)
                                file_stream.Write(buffer, 0, cnt);
                        }
                    }
                }

                Process process = new Process();
                process.StartInfo.FileName = pdf_executable;
                process.StartInfo.Arguments = "\"" + pdf_file + "\"";
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.UseShellExecute = false;
                process.Start();
            }
            catch(Exception ex)
            {
                MessageBox.Show(String.Format(Catalog.GetString("Cannot open manual: {0}"), ex.Message));
            }   
        }
    }
}
