package org.adrianvictor.lib.impl.r1_21.configuration;

import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.*;

public class Configuration implements org.adrianvictor.lib.configuration.provider.ConfigurationProvider {
    YamlConfiguration config = new YamlConfiguration();
    File configFile;

    @Override
    public void load(File file) throws IOException, org.adrianvictor.lib.configuration.exception.InvalidConfigurationException {
        try {
            config.load(file);
            configFile = file;
        } catch (InvalidConfigurationException e) {
            throw new org.adrianvictor.lib.configuration.exception.InvalidConfigurationException(e.getMessage());
        }
    }

    @Override
    public void load(String contents) throws IOException, org.adrianvictor.lib.configuration.exception.InvalidConfigurationException {
        try {
            config.load(contents);
        } catch (InvalidConfigurationException e) {
            throw new org.adrianvictor.lib.configuration.exception.InvalidConfigurationException(e.getMessage());
        }
    }

    @Override
    public void load(Reader reader) throws IOException, org.adrianvictor.lib.configuration.exception.InvalidConfigurationException {
        try {
            config.load(reader);
        } catch (InvalidConfigurationException e) {
            throw new org.adrianvictor.lib.configuration.exception.InvalidConfigurationException(e.getMessage());
        }
    }

    @Override
    public boolean save(File file) {
        try {
            config.save(file);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    @Override
    public boolean save() {
        try {
            config.save(configFile);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    @Override
    public String saveToString() {
        return config.saveToString();
    }

    @Override
    public Object getProperty(String path) {
        return config.get(path);
    }

    @Override
    public void setProperty(String path, Object value) {
        config.set(path, value);
    }

    @Override
    public Map<String, Object> getAll() {
        assert config.getRoot() != null;
        return config.getRoot().getValues(true);
    }

    @Override
    public boolean getBoolean(String path, boolean def) {
        return config.getBoolean(path, def);
    }

    @Override
    public List<Boolean> getBooleanList(String path, List<Boolean> def) {
        List<Boolean> result = config.getBooleanList(path);
        if (result.isEmpty()) result = def;
        return result;
    }

    @Override
    public double getDouble(String path, double def) {
        return config.getDouble(path, def);
    }

    @Override
    public List<Double> getDoubleList(String path, List<Double> def) {
        List<Double> result = config.getDoubleList(path);
        if (result.isEmpty()) result = def;
        return result;
    }

    @Override
    public int getInt(String path, int def) {
        return config.getInt(path, def);
    }

    @Override
    public String getString(String path) {
        return config.getString(path);
    }

    @Override
    public String getString(String path, String def) {
        return config.getString(path, def);
    }

    @Override
    public List<String> getStringList(String path, List<String> def) {
        List<String> result = config.getStringList(path);
        if (result.isEmpty()) result = def;
        return result;
    }

    @Override
    public List<Integer> getIntList(String path, List<Integer> def) {
        List<Integer> result = config.getIntegerList(path);
        if (result.isEmpty()) result = def;
        return result;
    }

    @Override
    public List<String> getKeys(String path) {
        Set<String> set = Objects.requireNonNull(config.getConfigurationSection(path)).getKeys(true);
        return set.stream().toList();
    }

    @Override
    public List<String> getKeys() {
        Set<String> set = Objects.requireNonNull(config.getRoot()).getKeys(true);
        return set.stream().toList();
    }

    @Override
    public List<Object> getList(String path) {
        return Collections.singletonList(config.getList(path));
    }
}
