/// <summary> Initialises helpers. </summary>
        /// <param name="generateDatabase"> Whether to read data from JSON instead of the database. </param>
        /// <param name="readOnlyJson"> Whether to generate the database. </param>
        /// <param name="readPreviouslyUnpackedJson"> Whether to extract game files. </param>
        private static void InitialiseHelpers(bool generateDatabase, bool readOnlyJson, bool readPreviouslyUnpackedJson)
        {
            var settingsTypes = new List <Type>
            {
                typeof(Settings),
                typeof(WpfSettings),
            };

            var requiredSettingNames = settingsTypes
                                       .SelectMany(settingsType => settingsType.GetProperties(BindingFlags.Public | BindingFlags.Static))
                                       .Where(settingProperty => settingProperty.GetCustomAttribute <RequiredSettingAttribute>() is RequiredSettingAttribute)
                                       .Select(settingProperty => settingProperty.Name);

            WindowFactory = new WindowFactory(Loggers);

            FileManager            = new WarThunderFileManager(Loggers);
            FileReader             = new WarThunderFileReader(Loggers);
            SettingsManager        = new WpfClientSettingsManager(FileManager, EWpfClientFile.Settings, requiredSettingNames, Loggers);
            _parser                = new Parser(Loggers);
            _unpacker              = new Unpacker(FileManager, Loggers);
            _dataRepositoryFactory = new DataRepositoryFactoryWarThunder(Loggers);
            _converter             = new Converter(Loggers);
            _jsonHelper            = new WarThunderJsonHelper(Loggers);
            _csvDeserializer       = new CsvDeserializer(Loggers);
            _randomizer            = new CustomRandomiserWithNormalisation(Loggers);
            _vehicleSelector       = new VehicleSelector(_randomizer, Loggers);
            _presetGenerator       = new PresetGenerator(_randomizer, _vehicleSelector, Loggers);
            _thunderSkillParser    = new ThunderSkillParser(Loggers);

            Manager = new WpfClientManager
                      (
                FileManager,
                FileReader,
                SettingsManager,
                _parser,
                _unpacker,
                _converter,
                _jsonHelper,
                _csvDeserializer,
                _dataRepositoryFactory,
                _randomizer,
                _vehicleSelector,
                _presetGenerator,
                _thunderSkillParser,
                generateDatabase,
                readOnlyJson,
                readPreviouslyUnpackedJson,
                Loggers
                      );
            InitialiseLocalisationManager();
        }
        /// <summary> The entry point. </summary>
        static void Main()
        {
            System.Console.Title = EClientApplicationName.WarThunderPresetRandomizer;
            var defaultColor = ConsoleColor.Gray;

            var requiredSettings = new List <string>
            {
                nameof(Settings.WarThunderLocation),
                nameof(Settings.KlensysWarThunderToolsLocation),
            };

            try
            {
                var loggers = new IConfiguredLogger[]
                {
                    new ConfiguredNLogger(ELoggerName.FileLogger, new ExceptionFormatter(), ESubdirectory.Logs),
                    new ConfiguredNLogger(ELoggerName.ConsoleLogger, new ExceptionFormatter()),
                };
                var fileManager           = new WarThunderFileManager(loggers);
                var fileReader            = new WarThunderFileReader(loggers);
                var settingsManager       = new WarThunderSettingsManager(fileManager, EConsoleClientFile.Settings, requiredSettings, loggers);
                var parser                = new Parser(loggers);
                var unpacker              = new Unpacker(fileManager, loggers);
                var dataRepositoryFactory = new DataRepositoryFactoryWarThunder(loggers);
                var converter             = new Converter(loggers);
                var jsonHelper            = new WarThunderJsonHelper(loggers);
                var csvDeserializer       = new CsvDeserializer(loggers);
                var randomiser            = new CustomRandomiser(loggers);
                var vehicleSelector       = new VehicleSelector(randomiser, loggers);
                var presetGenerator       = new PresetGenerator(randomiser, vehicleSelector, loggers);
                var thunderSkillParser    = new ThunderSkillParser(loggers);

                using (var manager = new Manager(fileManager, fileReader, settingsManager, parser, unpacker, converter, jsonHelper, csvDeserializer, dataRepositoryFactory, randomiser, vehicleSelector, presetGenerator, thunderSkillParser, true, false, false, loggers))
                {
                    manager.RemoveOldLogFiles();
                    manager.InitialiseGameClientVersion();

                    while (!settingsManager.WarThunderLocationIsValid())
                    {
                        System.Console.Write(EConsoleUiLogMessage.SelectValidLocation.Format(EApplicationName.WarThunder));
                        settingsManager.Save(nameof(Settings.WarThunderLocation), System.Console.ReadLine());
                    }
                    while (!settingsManager.KlensysWarThunderToolLocationIsValid())
                    {
                        System.Console.Write(EConsoleUiLogMessage.SelectValidLocation.Format(EApplicationName.KlensysWarThunderTools));
                        settingsManager.Save(nameof(Settings.KlensysWarThunderToolsLocation), System.Console.ReadLine());
                    }
                    System.Console.WriteLine();

                    manager.CacheData();

                    while (true)
                    {
                        var specification = ParseSpecification
                                            (
                            TakeSpecificationInput(),
                            manager
                            .ResearchTrees
                            .SelectMany(nationResearchTreeKeyValuePair => nationResearchTreeKeyValuePair.Value)
                            .SelectMany(branchKeyValuePair => branchKeyValuePair.Value)
                            .SelectMany(rankKeyValuePair => rankKeyValuePair.Value)
                            .Select(rankVehicleKeyValuePair => rankVehicleKeyValuePair.Value.GaijinId)
                                            );

                        foreach (var vehicle in manager.GeneratePrimaryAndFallbackPresets(specification)[EPreset.Primary])
                        {
                            System.Console.ForegroundColor = !vehicle.IsResearchable
                                ? ConsoleColor.Yellow
                                : ConsoleColor.White;

                            System.Console.WriteLine($"\t {vehicle.BattleRatingFormatted[specification.GameMode]} {vehicle.GaijinId}");
                        }

                        System.Console.ForegroundColor = defaultColor;
                    }
                }
            }
            catch
            {
                System.Console.Write($"\n{ECoreLogMessage.AnErrorHasOccurred} {EConsoleUiLogMessage.PressAnyKeyToExit} ");
                System.Console.ReadKey(true);
                Environment.Exit(0);
            }
        }