import java.io.*;
import java.util.Properties;

public interface ConfigEngine<T> {
    T load(String filePath);
    void save(T config, String filePath);
}

public class ConfigManager {
    private Map<Class<?>, ConfigEngine<?>> engines;

    public ConfigManager() {
        engines = new HashMap<>();
    }

    public <T> void registerEngine(Class<T> configClass, ConfigEngine<T> engine) {
        engines.put(configClass, engine);
    }

    @SuppressWarnings("unchecked")
    public <T> T loadConfig(Class<T> configClass, String filePath) {
        ConfigEngine<T> engine = (ConfigEngine<T>) engines.get(configClass);
        if (engine == null) {
            throw new IllegalArgumentException("No engine registered for class: " + configClass.getName());
        }
        return engine.load(filePath);
    }

    public <T> void saveConfig(T config, String filePath) {
        Class<?> configClass = config.getClass();
        @SuppressWarnings("unchecked")
        ConfigEngine<T> engine = (ConfigEngine<T>) engines.get(configClass);
        if (engine == null) {
            throw new IllegalArgumentException("No engine registered for class: " + configClass.getName());
        }
        engine.save(config, filePath);
    }
}

class BulletTrackingSettings {
    public int trackingMode;
}

class Bullet {
    public int bullet;
    public int bulletTracking;
}

class Range {
    public int range;
}

public class Config {
    public BulletTrackingSettings bulletTrackingSettings = new BulletTrackingSettings();
    public Bullet bullet = new Bullet();
    public Range range = new Range();
}

public class Main {
    public static void main(String[] args) {
        ConfigManager configManager = new ConfigManager();

        configManager.registerEngine(BulletTrackingSettings.class, new BulletTrackingSettingsEngine());
        configManager.registerEngine(Bullet.class, new BulletEngine());
        configManager.registerEngine(Range.class, new RangeEngine());

        BulletTrackingSettings bulletTrackingSettings = configManager.loadConfig(BulletTrackingSettings.class, "config.properties");
        System.out.println("BulletTrackingSettings.TrackingMode: " + bulletTrackingSettings.trackingMode);

        BulletTrackingSettings newSettings = new BulletTrackingSettings();
        newSettings.trackingMode = 3;
        configManager.saveConfig(newSettings, "config.properties");
    }
}

class BulletTrackingSettingsEngine implements ConfigEngine<BulletTrackingSettings> {
    @Override
    public BulletTrackingSettings load(String filePath) {
        BulletTrackingSettings settings = new BulletTrackingSettings();
        Properties props = new Properties();

        try (FileInputStream input = new FileInputStream(filePath)) {
            props.load(input);

            String trackingModeStr = props.getProperty("BulletTrackingSettings.TrackingMode");
            if (trackingModeStr != null) {
                settings.trackingMode = Integer.parseInt(trackingModeStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return settings;
    }

    @Override
    public void save(BulletTrackingSettings config, String filePath) {
        Properties props = new Properties();

        try (FileOutputStream output = new FileOutputStream(filePath)) {
            props.setProperty("BulletTrackingSettings.TrackingMode", Integer.toString(config.trackingMode));
            props.store(output, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class BulletEngine implements ConfigEngine<Bullet> {
    @Override
    public Bullet load(String filePath) {
        Bullet bullet = new Bullet();
        Properties props = new Properties();

        try (FileInputStream input = new FileInputStream(filePath)) {
            props.load(input);

            String bulletStr = props.getProperty("Bullet.Bullet");
            String bulletTrackingStr = props.getProperty("Bullet.BulletTracking");

            if (bulletStr != null) {
                bullet.bullet = Integer.parseInt(bulletStr);
            }
            if (bulletTrackingStr != null) {
                bullet.bulletTracking = Integer.parseInt(bulletTrackingStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bullet;
    }

    @Override
    public void save(Bullet config, String filePath) {
        Properties props = new Properties();

        try (FileOutputStream output = new FileOutputStream(filePath)) {
            props.setProperty("Bullet.Bullet", Integer.toString(config.bullet));
            props.setProperty("Bullet.BulletTracking", Integer.toString(config.bulletTracking));
            props.store(output, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class RangeEngine implements ConfigEngine<Range> {
    @Override
    public Range load(String filePath) {
        Range range = new Range();
        Properties props = new Properties();

        try (FileInputStream input = new FileInputStream(filePath)) {
            props.load(input);

            String rangeStr = props.getProperty("Range.Range");

            if (rangeStr != null) {
                range.range = Integer.parseInt(rangeStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return range;
    }

    @Override
    public void save(Range config, String filePath) {
        Properties props = new Properties();

        try (FileOutputStream output = new FileOutputStream(filePath)) {
            props.setProperty("Range.Range", Integer.toString(config.range));
            props.store(output, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}