private void MainTab_Selected(object sender, TabControlEventArgs args)
        {
            if ((sender == null) || (args == null))
            {
                Logging.LogNullError(nameof(sender) + " || " + nameof(args));
                return;
            }

            if (args.TabPage == RemoveTab)
            {
                ConfigPage configPage = OldTab as ConfigPage;
                if (configPage == null)
                {
                    MainTab.SelectedIndex = -1;
                    return;
                }

                if (configPage == ASFTab)
                {
                    MainTab.SelectedTab = ASFTab;
                    Logging.LogGenericErrorWithoutStacktrace("You can't remove global config!");
                    return;
                }

                MainTab.SelectedTab = configPage;

                if (DialogBox.YesNoBox("Removal", "Do you really want to remove this config?") != DialogResult.Yes)
                {
                    return;
                }

                MainTab.SelectedIndex = 0;
                configPage.ASFConfig.Remove();
                MainTab.TabPages.Remove(configPage);
            }
            else if (args.TabPage == RenameTab)
            {
                ConfigPage configPage = OldTab as ConfigPage;
                if (configPage == null)
                {
                    MainTab.SelectedIndex = -1;
                    return;
                }

                if (configPage == ASFTab)
                {
                    MainTab.SelectedTab = ASFTab;
                    Logging.LogGenericErrorWithoutStacktrace("You can't rename global config!");
                    return;
                }

                MainTab.SelectedTab = configPage;

                string input;
                if (DialogBox.InputBox("Rename", "Your new bot name:", out input) != DialogResult.OK)
                {
                    return;
                }

                if (string.IsNullOrEmpty(input))
                {
                    Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!");
                    return;
                }

                // Get rid of any potential whitespaces in bot name
                input = Regex.Replace(input, @"\s+", "");

                configPage.ASFConfig.Rename(input);
                configPage.RefreshText();
            }
            else if (args.TabPage == NewTab)
            {
                ConfigPage configPage = OldTab as ConfigPage;
                if (configPage == null)
                {
                    MainTab.SelectedIndex = -1;
                    return;
                }

                MainTab.SelectedTab = configPage;

                Tutorial.OnAction(Tutorial.EPhase.BotNickname);

                string input;
                if (DialogBox.InputBox("New", "Your new bot name:", out input) != DialogResult.OK)
                {
                    return;
                }

                if (string.IsNullOrEmpty(input))
                {
                    Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!");
                    return;
                }

                // Get rid of any potential whitespaces in bot name
                input = Regex.Replace(input, @"\s+", "");

                if (ASFConfig.ASFConfigs.Select(config => Path.GetFileNameWithoutExtension(config.FilePath)).Any(fileNameWithoutExtension => (fileNameWithoutExtension == null) || fileNameWithoutExtension.Equals(input)))
                {
                    Logging.LogGenericErrorWithoutStacktrace("Bot with such name exists already!");
                    return;
                }

                input = Path.Combine(Program.ConfigDirectory, input + ".json");

                ConfigPage newConfigPage = new ConfigPage(BotConfig.Load(input));
                MainTab.TabPages.Insert(MainTab.TabPages.Count - ReservedTabs, newConfigPage);
                MainTab.SelectedTab = newConfigPage;
                Tutorial.OnAction(Tutorial.EPhase.BotNicknameFinished);
            }
            else if (args.TabPage == ASFTab)
            {
                Tutorial.OnAction(Tutorial.EPhase.GlobalConfigOpened);
            }
        }
        internal static GlobalConfig Load(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return(null);
            }

            if (!File.Exists(filePath))
            {
                return(new GlobalConfig(filePath));
            }

            GlobalConfig globalConfig;

            try {
                globalConfig = JsonConvert.DeserializeObject <GlobalConfig>(File.ReadAllText(filePath));
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return(new GlobalConfig(filePath));
            }

            if (globalConfig == null)
            {
                return(new GlobalConfig(filePath));
            }

            globalConfig.FilePath = filePath;

            // SK2 supports only TCP and UDP steam protocols
            // Ensure that user can't screw this up
            switch (globalConfig.SteamProtocol)
            {
            case ProtocolType.Tcp:
            case ProtocolType.Udp:
                break;

            default:
                Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead");
                globalConfig.SteamProtocol = DefaultSteamProtocol;
                break;
            }

            // User might not know what he's doing
            // Ensure that he can't screw core ASF variables
            if (globalConfig.MaxFarmingTime == 0)
            {
                Logging.LogGenericWarning("Configured MaxFarmingTime is invalid: " + globalConfig.MaxFarmingTime + ". Value of " + DefaultMaxFarmingTime + " will be used instead");
                globalConfig.MaxFarmingTime = DefaultMaxFarmingTime;
            }

            if (globalConfig.FarmingDelay == 0)
            {
                Logging.LogGenericWarning("Configured FarmingDelay is invalid: " + globalConfig.FarmingDelay + ". Value of " + DefaultFarmingDelay + " will be used instead");
                globalConfig.FarmingDelay = DefaultFarmingDelay;
            }

            if (globalConfig.HttpTimeout == 0)
            {
                Logging.LogGenericWarning("Configured HttpTimeout is invalid: " + globalConfig.HttpTimeout + ". Value of " + DefaultHttpTimeout + " will be used instead");
                globalConfig.HttpTimeout = DefaultHttpTimeout;
            }

            if (globalConfig.WCFPort == 0)
            {
                Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead");
                globalConfig.WCFPort = DefaultWCFPort;
            }

            return(globalConfig);
        }