/*
         * Deserialization:
         */

        public void Apply()
        {
            // Read *.xml file:
            XDocument xmlDoc  = XDocument.Load(this.filePath);
            XElement  xmlRoot = xmlDoc.Element("Language");

            foreach (LocalizedForm form in Localization.LocalizedForms)
            {
                XElement xmlForm = xmlRoot.Element(form.Form.Name);
                if (xmlForm == null)
                {
                    throw new InvalidXmlException($"Couldn't find <{form.Form.Name}>");
                }

                // Set title, if it exists:
                if (xmlForm.Attribute("title") != null)
                {
                    form.Form.Text = xmlForm.Attribute("title").Value;
                }

                // Forms:
                DeserializeDictionaries(xmlRoot);
                DeserializeControls(xmlForm, form.Form, form.ToolTip);
                foreach (Control subControl in form.SpecialControls)
                {
                    DeserializeControl(xmlForm, subControl, form.ToolTip);
                }

                // Message boxes:
                XElement xmlMsgBox = xmlRoot.Element("Messageboxes");
                if (xmlMsgBox != null)
                {
                    MsgBox.Deserialize(xmlMsgBox);
                }

                // Strings:
                XElement xmlStrings = xmlRoot.Element("Strings");
                if (xmlStrings != null)
                {
                    Localization.DeserializeStrings(xmlStrings);
                }

                // Drop downs:
                XElement xmlDropDowns = xmlRoot.Element("Dropdowns");
                if (xmlDropDowns != null)
                {
                    DropDown.DeserializeAll(xmlDropDowns);
                }
            }
        }
        /// <summary>
        /// Sets up elements, adds event handlers, etc.
        /// </summary>
        private void InitializeDetailControls()
        {
            DropDown.Add("ModInstallAs", new DropDown(
                             this.comboBoxModInstallAs,
                             new string[] {
                "Bundled *.ba2 archive",
                "Separate *.ba2 archive",
                "Loose files"
            }
                             ));

            DropDown.Add("ModArchivePreset", new DropDown(
                             this.comboBoxModArchivePreset,
                             new string[] {
                "-- Please select --",
                "Auto-detect",
                "General / Interface / Materials / Animations",     /* Materials: *.bgsm; Interface: *.swf; */
                "Textures (*.dds files)",
                "Sound FX / Music / Voice",                         /* Voice: *.fuz; Lip-Sync: *.lip; Sound FX: *.xwm; */
            }
                             ));

            this.pictureBoxCollapseDetails.MouseEnter += new EventHandler((mouseSender, mouseEventArgs) =>
            {
                this.pictureBoxCollapseDetails.BackColor = Color.LightGray;
                this.pictureBoxCollapseDetails.Cursor    = Cursors.Hand;
            });
            this.pictureBoxCollapseDetails.MouseLeave += new EventHandler((mouseSender, mouseEventArgs) =>
            {
                this.pictureBoxCollapseDetails.BackColor = Color.Silver;
                this.pictureBoxCollapseDetails.Cursor    = Cursors.Hand;
            });

            this.Resize += this.FormModsDetails_Resize;

            // Disable scroll wheel on UI elements to prevent the user from accidentally changing values:
            Utils.PreventChangeOnMouseWheelForAllElements(this.panelModDetailsInner);

            /*
             * Drag&Drop
             */
            this.panelModDetailsReplaceDragAndDrop.AllowDrop  = true;
            this.panelModDetailsReplaceDragAndDrop.DragEnter += new DragEventHandler(panelModDetailsReplaceDragAndDrop_DragEnter);
            this.panelModDetailsReplaceDragAndDrop.DragDrop  += new DragEventHandler(panelModDetailsReplaceDragAndDrop_DragDrop);

            CloseSidePanel();
        }
        /*
         * Serialization:
         */

        public void Save(String fileName, String version)
        {
            String newFileName = fileName;
            String newFilePath = Path.Combine(Localization.languageFolder, newFileName);

            // Create document and root:
            XDocument xmlDoc  = new XDocument();
            XElement  xmlRoot = new XElement("Language");

            xmlRoot.Add(new XAttribute("name", this.Name));
            xmlRoot.Add(new XAttribute("iso", this.ISO));
            if (this.ISO != "en-US" && this.Author.Length > 0)
            {
                xmlRoot.Add(new XAttribute("author", this.Author));
            }
            if (this.ISO == "en-US")
            {
                xmlDoc.AddFirst(new XComment("\n     This file is auto-generated on program start.\n     Therefore any changes made to this file will be overriden.\n     You can use this as a template for your own translation, though.\n"));
            }
            xmlRoot.Add(new XAttribute("version", version));
            xmlDoc.Add(xmlRoot);

            // Serialize external stuff:
            xmlRoot.Add(Localization.SerializeStrings());
            xmlRoot.Add(DropDown.SerializeAll());
            xmlRoot.Add(MsgBox.SerializeAll());

            // Serialize all control elements:
            foreach (LocalizedForm form in Localization.LocalizedForms)
            {
                XElement xmlForm = new XElement(form.Form.Name, new XAttribute("title", form.Form.Text));
                SerializeControls(xmlForm, form.Form, form.ToolTip);
                foreach (Control control in form.SpecialControls)
                {
                    SerializeControl(xmlForm, control, form.ToolTip);
                }
                xmlRoot.Add(xmlForm);
            }

            // Save it:
            if (!Directory.Exists(Localization.languageFolder))
            {
                Directory.CreateDirectory(Localization.languageFolder);
            }

            xmlDoc.Save(newFilePath);
        }
        /// <summary>
        /// Assigns a dropdown menu to hold all languages.
        /// Also assigns an event handler 'SelectedIndexChanged' to automatically translate forms.
        /// </summary>
        /// <param name="comboBoxLanguage"></param>
        public static void AssignDropDown(ComboBox comboBoxLanguage)
        {
            Localization.comboBoxTranslations      = new DropDown(comboBoxLanguage);
            comboBoxLanguage.SelectedIndexChanged += (object sender, EventArgs e) =>
            {
                Translation translation = Localization.GetTranslation();
                translation.Apply();

                IniFiles.Config.Set("Preferences", "sLanguage", translation.ISO);
                Localization.Locale = translation.ISO;

                if (translation.ISO != "en-US")
                {
                    Localization.GenerateTemplate(translation);
                }
            };
        }
        public static void DeserializeAll(XElement xmlDropDowns)
        {
            /*
             * <Dropdowns>
             *   ...
             * </Dropdowns>
             */

            // Go through every dropdown
            foreach (XElement xmlDropDown in xmlDropDowns.Descendants("Dropdown"))
            {
                // Get id:
                String id = xmlDropDown.Attribute("id").Value;

                // If such a combobox exists, deserialize:
                if (DropDown.ContainsKey(id))
                {
                    DropDown.Get(id).Deserialize(xmlDropDown);
                }
            }
        }
        /*
         * Serialization:
         */

        public void Save(string fileName, string version)
        {
            string newFileName = fileName;
            string newFilePath = Path.Combine(Localization.LanguageFolder, newFileName);

            // Create document and root:
            XDocument xmlDoc  = new XDocument();
            XElement  xmlRoot = new XElement("Language");

            xmlRoot.Add(new XAttribute("name", this.Name));
            xmlRoot.Add(new XAttribute("iso", this.ISO));
            if (this.ISO != "en-US" && this.Author.Length > 0)
            {
                xmlRoot.Add(new XAttribute("author", this.Author));
            }

            if (this.ISO == "en-US")
            {
                xmlDoc.AddFirst(
                    new XComment("\n" +
                                 "     This file is auto-generated on program start.\n" +
                                 "     Therefore any changes made to this file will be overwritten.\n" +
                                 "     You can use this as a template for your own translation, though.\n" +
                                 "\n" +
                                 "     If you need help with translating, you can find a guide here:\n" +
                                 "     https://github.com/FelisDiligens/Fallout76-QuickConfiguration/wiki/Translations\n"));
            }
            else
            {
                xmlDoc.AddFirst(
                    new XComment("\n" +
                                 "     This is a template that contains some of the already translated elements.\n" +
                                 "     You can rename it from \"*.template.xml\" to \"*.xml\" and translate the added elements.\n" +
                                 "\n" +
                                 "     If you need help with translating, you can find a guide here:\n" +
                                 "     https://github.com/FelisDiligens/Fallout76-QuickConfiguration/wiki/Translations\n"));
            }

            xmlRoot.Add(new XAttribute("version", version));
            xmlDoc.Add(xmlRoot);

            // Serialize external stuff:
            // TODO: Find a way to remove the references, plz:
            XElement xmlStrings      = Localization.SerializeStrings();
            XElement xmlDropDowns    = DropDown.SerializeAll();
            XElement xmlMsgBoxes     = MsgBox.SerializeAll();
            XElement xmlDescriptions = LinkedTweaks.SerializeTweakDescriptionList();
            string   separator       = "".PadLeft(150, '*');

            xmlStrings.AddFirst(new XComment($"\n        Strings\n        {separator}\n        Basically little text snippets that can be used everywhere.\n    "));
            xmlDropDowns.AddFirst(new XComment($"\n        Dropdowns\n        {separator}\n        Make sure that the amount of options stays the same.\n    "));
            xmlMsgBoxes.AddFirst(new XComment($"\n        Message boxes\n        {separator}\n        The {"{0}"} is a placeholder, btw.\n    "));
            xmlDescriptions.AddFirst(new XComment($"\n        Descriptions\n        {separator}\n        These are the descriptions of almost all tweaks.\n        They appear in tool tips, when the user hovers over a tweak with the mouse cursor.\n    "));
            xmlRoot.Add(xmlStrings);
            xmlRoot.Add(xmlDropDowns);
            xmlRoot.Add(xmlMsgBoxes);
            xmlRoot.Add(xmlDescriptions);

            ignoreTooltipsOfTheseControls = LinkedTweaks.GetListOfLinkedControlNames();

            // Serialize all control elements:
            foreach (LocalizedForm form in Localization.LocalizedForms)
            {
                XElement xmlForm = new XElement(form.Form.Name, new XAttribute("title", form.Form.Text));
                xmlForm.AddFirst(new XComment($"\n        {form.Form.Name}\n        {separator}\n        {form.Form.Text}\n    "));
                SerializeControls(xmlForm, form.Form, form.ToolTip);
                foreach (Control control in form.SpecialControls)
                {
                    SerializeControl(xmlForm, control, form.ToolTip);
                }
                xmlRoot.Add(xmlForm);
            }

            // Save it:
            Directory.CreateDirectory(Localization.LanguageFolder);
            xmlDoc.Save(newFilePath);
        }
        /*
         * Deserialization:
         */

        public void Apply()
        {
            try
            {
                // Read *.xml file:
                XDocument xmlDoc  = XDocument.Load(this.filePath);
                XElement  xmlRoot = xmlDoc.Element("Language");

                ignoreTooltipsOfTheseControls = LinkedTweaks.GetListOfLinkedControlNames();

                // Translate each form individually:
                foreach (LocalizedForm form in Localization.LocalizedForms)
                {
                    XElement xmlForm = xmlRoot.Element(form.Form.Name);

                    // Ignore non-existing forms
                    if (xmlForm == null)
                    {
                        continue; // throw new InvalidXmlException($"Couldn't find <{form.Form.Name}>");
                    }
                    // Set title, if it exists:
                    if (xmlForm.Attribute("title") != null)
                    {
                        form.Form.Text = xmlForm.Attribute("title").Value;
                    }

                    // Forms:
                    DeserializeDictionaries(xmlForm); // TODO: xmlRoot replaced with xmlForm. Good idea?
                    DeserializeControls(xmlForm, form.Form, form.ToolTip);
                    foreach (Control subControl in form.SpecialControls)
                    {
                        DeserializeControl(xmlForm, subControl, form.ToolTip);
                    }

                    // Message boxes:
                    XElement xmlMsgBox = xmlRoot.Element("Messageboxes");
                    if (xmlMsgBox != null)
                    {
                        MsgBox.Deserialize(xmlMsgBox);
                    }

                    // Strings:
                    XElement xmlStrings = xmlRoot.Element("Strings");
                    if (xmlStrings != null)
                    {
                        Localization.DeserializeStrings(xmlStrings);
                    }

                    // TODO: Generalize this. No outside references, plz:

                    // TODO: Doesn't make sense to deserialize them multiple times:

                    // Drop downs:
                    XElement xmlDropDowns = xmlRoot.Element("Dropdowns");
                    if (xmlDropDowns != null)
                    {
                        DropDown.DeserializeAll(xmlDropDowns);
                    }

                    // Tweak descriptions:
                    XElement xmlTweakDescriptions = xmlRoot.Element("TweakDescriptions");
                    if (xmlTweakDescriptions != null)
                    {
                        LinkedTweaks.DeserializeTweakDescriptionList(xmlTweakDescriptions);
                    }
                    if (form.ToolTip != null)
                    {
                        LinkedTweaks.SetToolTips(); // TODO: No need to call it per form anymore
                    }
                }

                // Call event handler:
                if (LanguageChanged != null)
                {
                    TranslationEventArgs e = new TranslationEventArgs();
                    e.HasAuthor = this.Author != "";
                    //e.ActiveTranslation = this;
                    LanguageChanged(this, e);
                }
            }
            catch (Exception exc)
            {
                MsgBox.Show("Loading translation failed", $"The translation '{Path.GetFileNameWithoutExtension(filePath)}' couldn't be loaded.\n{exc.GetType()}: {exc.Message}", MessageBoxIcon.Error);
            }
        }
        public Form1()
        {
            InitializeComponent();

            // Determine whether this is the very first start of the tool on the system:
            FirstStart = !File.Exists(IniFiles.ConfigPath) && !File.Exists(ProfileManager.XMLPath);

            // Handle changes:
            ProfileManager.ProfileChanged += OnProfileChanged;

            // Create FormMods:
            formMods = new FormMods();
            FormMods.NWModeUpdated += OnNWModeUpdated;
            UpdateNWModeUI(false);

            /*
             * Translations
             */

            // Make this form translatable:
            LocalizedForm form = new LocalizedForm(this, this.toolTip);

            form.SpecialControls.Add(this.contextMenuStripGallery);
            Localization.LocalizedForms.Add(form);

            // Handle translations:
            Translation.LanguageChanged += OnLanguageChanged;

            // Add control elements to blacklist:
            Translation.BlackList.AddRange(new string[] {
                "labelConfigVersion",
                "labelAuthorName",
                "labelTranslationAuthor",
                "groupBoxWIP",
                "labelNewVersion",
                "labelGameEdition",
                "toolStripStatusLabelGameText",
                "toolStripStatusLabelEditionText",
                "toolStripStatusLabel1",
                "labelPipboyResolutionSpacer"
            });


            /*
             * Dropdowns
             */

            #region Dropdowns

            // Let's add options to the drop-down menus:

            // Display resolution usage statistics (and lists):
            // https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam
            // https://www.rapidtables.com/web/dev/screen-resolution-statistics.html
            // https://w3codemasters.in/most-common-screen-resolutions/
            // https://www.reneelab.com/video-with-4-3-format.html
            // https://www.overclock.net/threads/list-of-display-resolutions-aspect-ratios.539967/
            // https://en.wikipedia.org/wiki/List_of_common_resolutions
            DropDown.Add("Resolution", new DropDown(
                             this.comboBoxResolution,
                             new string[] {
                "Custom",
                "",
                "┌───────────────────────────────┐",
                "│  4:3                          │",
                "├───────────────────────────────┤",
                "│ [4:3]    640 x  480 (VGA)     │",
                "│ [4:3]    800 x  600 (SVGA)    │",
                "│ [4:3]    960 x  720           │",
                "│ [4:3]   1024 x  768 (XGA)     │",
                "│ [4:3]   1152 x  864           │",
                "│ [4:3]   1280 x  960           │",
                "│ [4:3]   1400 x 1050           │",
                "│ [4:3]   1440 x 1080           │",
                "│ [4:3]   1600 x 1200           │",
                "│ [4:3]   1920 x 1440           │",
                "│ [4:3]   2048 x 1536           │",
                "│ [4:3]   2880 x 2160           │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  5:3                          │",
                "├───────────────────────────────┤",
                "│ [5:3]    800 x  480           │",
                "│ [5:3]   1280 x  768 (WXGA)    │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  5:4                          │",
                "├───────────────────────────────┤",
                "│ [5:4]   1152 x  960           │",
                "│ [5:4]   1280 x 1024           │",
                "│ [5:4]   2560 x 2048           │",
                "│ [5:4]   5120 x 4096           │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  8:5                          │",
                "├───────────────────────────────┤",
                "│ [8:5]   1280 x  800           │",
                "│ [8:5]   1440 x  900           │",
                "│ [8:5]   1680 x 1050           │",
                "│ [8:5]   1920 x 1200           │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  16:9                         │",
                "├───────────────────────────────┤",
                "│ [16:9]  1024 x  576           │",
                "│ [16:9]  1152 x  648           │",
                "│ [16:9]  1280 x  720 (HD)      │",
                "│ [16:9]  1360 x  768           │",
                "│ [16:9]  1365 x  768           │",
                "│ [16:9]  1366 x  768           │",
                "│ [16:9]  1536 x  864           │",
                "│ [16:9]  1600 x  900           │",
                "│ [16:9]  1920 x 1080 (Full HD) │",
                "│ [16:9]  2560 x 1440 (WQHD)    │",
                "│ [16:9]  3200 x 1800           │",
                "│ [16:9]  3840 x 2160 (4K UHD1) │",
                "│ [16:9]  5120 x 2880 (5K)      │",
                "│ [16:9]  7680 x 4320 (8K UHD2) │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  16:10                        │",
                "├───────────────────────────────┤",
                "│ [16:10]  640 x  400           │",
                "│ [16:10] 1280 x  800           │",
                "│ [16:10] 1440 x  900           │",
                "│ [16:10] 1680 x 1050           │",
                "│ [16:10] 1920 x 1200           │",
                "│ [16:10] 2560 x 1600           │",
                "│ [16:10] 3840 x 2400           │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  17:9                         │",
                "├───────────────────────────────┤",
                "│ [17:9]  2048 x 1080           │",
                "│                               │",
                "│                               │",
                "├───────────────────────────────┤",
                "│  21:9                         │",
                "├───────────────────────────────┤",
                "│ [21:9]  1920 x  800           │",
                "│ [21:9]  2560 x 1080           │",
                "│ [21:9]  3440 x 1440           │",
                "│ [21:9]  3840 x 1600           │",
                "│ [21:9]  5120 x 2160           │",
                "│                               │",
                "│                               │",
                "└───────────────────────────────┘",
                ""
            }
                             ));

            DropDown.Add("DisplayMode", new DropDown(
                             this.comboBoxDisplayMode,
                             new string[] {
                "Fullscreen",
                "Windowed",
                "Borderless windowed",
                "Borderless windowed (Fullscreen)"
            }
                             ));

            DropDown.Add("AntiAliasing", new DropDown(
                             this.comboBoxAntiAliasing,
                             new string[] {
                "TAA (default)",
                "FXAA",
                "Disabled"
            }
                             ));

            DropDown.Add("AnisotropicFiltering", new DropDown(
                             this.comboBoxAnisotropicFiltering,
                             new string[] {
                "None",
                "2x",
                "4x",
                "8x (default)",
                "16x"
            }
                             ));

            DropDown.Add("ShadowTextureResolution", new DropDown(
                             this.comboBoxShadowTextureResolution,
                             new string[] {
                "512 = Potato",
                "1024 = Low",
                "2048 = High (default)",
                "4096 = Ultra"
            }
                             ));

            DropDown.Add("ShadowBlurriness", new DropDown(
                             this.comboBoxShadowBlurriness,
                             new string[] {
                "1x",
                "2x",
                "3x = Default, recommended"
            }
                             ));

            DropDown.Add("VoiceChatMode", new DropDown(
                             this.comboBoxVoiceChatMode,
                             new string[] {
                "Auto",
                "Area",
                "Team",
                "None"
            }
                             ));

            DropDown.Add("ShowActiveEffectsOnHUD", new DropDown(
                             this.comboBoxShowActiveEffectsOnHUD,
                             new string[] {
                "Disabled",
                "Detrimental",
                "All"
            }
                             ));

            DropDown.Add("iDirShadowSplits", new DropDown(
                             this.comboBoxiDirShadowSplits,
                             new string[] {
                "1 - Low",
                "2 - High / Medium",
                "3 - Ultra"
            }
                             ));

            #endregion

            /*
             * Event handlers:
             */

            // Disable scroll wheel on UI elements to prevent the user from accidentally changing values:
            Utils.PreventChangeOnMouseWheelForAllElements(this);

            // Event handler:
            this.FormClosing += this.Form1_FormClosing;
            this.Shown       += this.Form1_Shown;
            this.KeyDown     += this.Form1_KeyDown;

            this.backgroundWorkerGetLatestVersion.RunWorkerCompleted += backgroundWorkerGetLatestVersion_RunWorkerCompleted;

            InitAccountProfileRadiobuttons();

            // Pipboy screen preview:
            InitPipboyScreen();
            this.colorPreviewPipboy.BackColorChanged += colorPreviewPipboy_BackColorChanged;

            // Danger Zone:
            this.tabControl1.TabPages.Remove(this.tabPageDangerZone);
            FormSettings.SettingsClosing += (object sender, EventArgs e) =>
            {
                if (FormSettings.DangerZoneEnabled && !this.tabControl1.TabPages.Contains(this.tabPageDangerZone))
                {
                    this.tabControl1.TabPages.Add(this.tabPageDangerZone);
                    LinkDangerZoneControls();
                }
            };
        }
 public static void AssignDropBox(ComboBox comboBoxLanguage)
 {
     Localization.comboBoxTranslations = new DropDown(comboBoxLanguage);
 }
 public static void Add(String key, DropDown comboBox)
 {
     Dict.Add(key, comboBox);
 }