Inheritance: AcManager.Tools.AcObjectsNew.AcIniObject
        public bool Apply(WeatherObject weather) {
            if (AcRootDirectory.Instance.Value == null) return false;

            var source = Path.Combine(weather.Location, RelativeSource);
            if (!Directory.Exists(source)) return false;

            var destination = Path.Combine(AcRootDirectory.Instance.RequireValue, RelativeDestination);
            var backup = Path.Combine(AcRootDirectory.Instance.RequireValue, RelativeBackup);

            if (Directory.Exists(destination)) {
                if (Directory.Exists(backup)) {
                    Directory.Move(backup, FileUtils.EnsureUnique(backup));
                }

                Logging.Debug($"{destination} → {backup}");
                Directory.Move(destination, backup);
            }


            try {
                Logging.Debug($"{source} → {destination}");
                FileUtils.CopyRecursiveHardlink(source, destination);
            } catch (Exception e) {
                // this exception should be catched here so original clouds folder still
                // will be restored even when copying a new one has been failed
                NonfatalError.Notify("Can’t replace weather-specific directory", e);
            }

            return true;
        }
            public bool WeatherIcon(Table v)
            {
                var icons = _data?.GetKeys(GetText(v, "icons") ?? "").ToList();

                if (icons == null || icons.Count == 0)
                {
                    Logging.Warning($"Icons not found: {GetText(v, "icons")}");
                    return(false);
                }

                if (_texturesContext.Weather == null)
                {
                    return(false);
                }

                var weatherType = _texturesContext.Weather.Type;

                if (weatherType == WeatherType.None)
                {
                    weatherType = WeatherObject.TryToDetectWeatherTypeById(_texturesContext.Weather.Id);
                }

                var availableTypes = icons.Select(x => new {
                    Type     = Enum.TryParse <WeatherType>(Regex.Replace(x, @"^.*/|\.\w+$|\W", ""), true, out var type) ? type : WeatherType.None,
                    FileName = x
                }).ToList();
        protected override bool SetOverride(WeatherObject weather) {
            _replacement = Path.Combine(weather.Location, "filter.ini");
            if (!File.Exists(_replacement)) return false;

            _destination = Destination;
            if (File.Exists(_destination)) {
                File.Delete(_destination);
            }
            
            FileUtils.Hardlink(_replacement, _destination);

            var ini = new IniFile(FileUtils.GetCfgVideoFilename());
            var section = ini["POST_PROCESS"];
            section.Set("__OGIRINAL_FILTER", section.GetNonEmpty("FILTER"));
            section.Set("FILTER", FilterId);
            ini.Save();

            return true;
        }
 protected abstract bool SetOverride(WeatherObject weather);
 protected override bool SetOverride(WeatherObject weather) {
     return Replacements.Aggregate(false, (current, replacement) => replacement.Apply(weather) || current);
 }