// <copyright file="Program.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>

namespace FSI.BT.Tools
{
    using System;
    using System.Drawing;
    using System.IO;
    using System.IO.Compression;
    using System.Reflection;
    using System.Windows.Forms;
    using System.Windows.Input;
    using Config.Net;
    using Config.Net.Stores;
    using FSI.BT.Tools.Global.Utilities;
    using FSI.BT.Tools.SystemTrayMenu;
    using FSI.BT.Tools.SystemTrayMenu.Utilities;
    using Tulpep.NotificationWindow;

    internal static class Program
    {
        private static bool isStartup = true;

        public static void CopyStream(Stream input, Stream output)
        {
            // Insert null checking here for production
            byte[] buffer = new byte[8192];

            int bytesRead;
            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }

        [STAThread]
        private static void Main(string[] args)
        {
           
            // Json-Files, die kopiert werden sollen
            string[] jsonFiles = {
                "FSI.BT.Tools.Global.json",
                "FSI.BT.Tools.RadialMenu.json",
                "FSI.BT.Tools.SystemTrayMenu.json",
                "FSI.BT.Tools.TimeStamp.json",
            };

            // Zielpfad zusammenstellen (aktuelles User-Verzeichnis + FSI.BT.Tools)
            var jsonPath = Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\OneDrive - Fondium Group GmbH\\.FSI.BT.Tools");

            // alle json-Files Durchlaufen und ins Userverzeichnis speichern
            foreach (string jsonFile in jsonFiles)
            {
                Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(jsonFile);

                try
                {
                    FileStream fileStream = new FileStream(Path.Combine(jsonPath.FullName, jsonFile.Replace("FSI.BT.Tools.", string.Empty)), FileMode.CreateNew);
                    for (int i = 0; i < stream.Length; i++)
                        fileStream.WriteByte((byte)stream.ReadByte());
                    fileStream.Close();
                }
                catch (Exception ex)
                {
                    Global.Vars.Log.Error(ex.Message);
                }
            }


            string[] externalTools =
            {
                "FSI.BT.Tools.ExtTools.kalk.zip",
                "FSI.BT.Tools.ExtTools.AudioSwitch.zip",
                "FSI.BT.Tools.ExtTools.SmartSystemMenu_v2.21.2.zip",
            };

            try
            {
                foreach (var externalTool in externalTools)
                {
                    ExtractEmbeddedZip.Extract(externalTool, Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\ExtTools\\");
                }
            }
            catch (Exception ex)
            {
                Global.Vars.Log.Error(ex.Message);
            }

            try
            {
                // Einstellungen Global
                JsonConfigStore _storeGlobal = new(Path.Combine(jsonPath.FullName, jsonFiles[0].Replace("FSI.BT.Tools.", String.Empty)), true);
                Global.Vars.GlobalSettings = new ConfigurationBuilder<Global.Settings.Interface.IInterface>()
                        .UseConfigStore(_storeGlobal)
                        .Build();

                // Einstellungen für Radial-Menü
                JsonConfigStore _storeRadialMenu = new(Path.Combine(jsonPath.FullName, jsonFiles[1].Replace("FSI.BT.Tools.", String.Empty)), true);
                Global.Vars.RadialMenuSettings = new ConfigurationBuilder<RadialMenu.Settings.Interface.IInterface>()
                        .UseConfigStore(_storeRadialMenu)
                        .Build();

                // Einstellungen für System-Tray-Menü
                JsonConfigStore _storeSystemTrayMenu = new(Path.Combine(jsonPath.FullName, jsonFiles[2].Replace("FSI.BT.Tools.", String.Empty)), true);
                Global.Vars.SystemTrayMenuSettings = new ConfigurationBuilder<SystemTrayMenu.Settings.Interface.IInterface>()
                        .UseConfigStore(_storeSystemTrayMenu)
                        .Build();

                // Einstellungen für Zeitstempel in Zwischenablage kopieren
                JsonConfigStore _storeTimeStamp = new(Path.Combine(jsonPath.FullName, jsonFiles[3].Replace("FSI.BT.Tools.", String.Empty)), true);
                Global.Vars.TimeStampSettings = new ConfigurationBuilder<TimeStampToClipboard.Settings.Interface.IInterface>()
                        .UseConfigStore(_storeTimeStamp)
                        .Build();


                Global.Vars.UserRights = Admin.CheckUserRight();
                Global.Vars.AdminRights = Admin.CheckAdminRight();
                Global.Vars.SuperAdminRights = Admin.CheckSuperAdminRight();

                Log.Initialize();
                Translator.Initialize();
                Config.SetFolderByWindowsContextMenu(args);
                Config.LoadOrSetByUser();
                Config.Initialize();

                if (SingleAppInstance.Initialize())
                {

                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.ThreadException += Application_ThreadException;
                    Scaling.Initialize();
                    FolderOptions.Initialize();

                    using (new ClipboardMgt.App())
                    {
                        isStartup = false;
                    }

                    using (new TimeStampToClipboard.App())
                    {
                        isStartup = false;
                    }

                    using (new FSI.BT.Tools.RadialMenu.App())
                    {
                        isStartup = false;
                    }

                    using (new FSI.BT.Tools.SystemTrayMenu.App())
                    {
                        isStartup = false;
                        Log.WriteApplicationRuns();
                        Application.Run();
                    }
                }



                Application.ThreadException -= Application_ThreadException;
                Config.Dispose();
            }
            catch (Exception ex)
            {
                AskUserSendError(ex);
            }
            finally
            {
                Log.Close();
            }
        }


        private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            AskUserSendError(e.Exception);
        }

        private static void AskUserSendError(Exception ex)
        {
            Log.Error("Application Crashed", ex);

            DialogResult dialogResult = MessageBox.Show(
                "A problem has been encountered and the application needs to restart. " +
                "Reporting this error will help us make our product better. " +
                "Press 'Yes' to open your standard email app (emailto: Markus@Hofknecht.eu). " + Environment.NewLine +
                @"You can also create an issue manually here https://github.com/Hofknecht/SystemTrayMenu/issues" + Environment.NewLine +
                "Press 'Cancel' to quit SystemTrayMenu.",
                "SystemTrayMenu Crashed",
                MessageBoxButtons.YesNoCancel);

            if (dialogResult == DialogResult.Yes)
            {
                Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
                    "?subject=SystemTrayMenu Bug reported " +
                    Assembly.GetEntryAssembly().GetName().Version +
                    "&body=" + ex.ToString());
            }

            if (!isStartup && dialogResult != DialogResult.Cancel)
            {
                AppRestart.ByThreadException();
            }
        }
    }
}