package zenith.zov.client.modules.api.setting.impl;

import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Generated;
import zenith.zov.client.modules.api.setting.Setting;

public class MultiBooleanSetting extends Setting {
    private final List<MultiBooleanSetting.Value> booleanSettings;

    public MultiBooleanSetting(String name) {
        super(name);
        this.booleanSettings = new ArrayList<>();
    }

    public MultiBooleanSetting(String name, MultiBooleanSetting.Value... settings) {
        super(name);
        this.booleanSettings = new ArrayList<>(Arrays.asList(settings));
    }

    public MultiBooleanSetting.Value getValueByName(String settingName) {
        return this.booleanSettings.stream().filter(s -> s.getName().equalsIgnoreCase(settingName)).findFirst().orElse(null);
    }

    public static MultiBooleanSetting create(String name, List<String> values) {
        MultiBooleanSetting.Value[] booleanSettings = values.stream()
            .map(value -> new MultiBooleanSetting.Value(value, true))
            .toArray(MultiBooleanSetting.Value[]::new);
        return new MultiBooleanSetting(name, booleanSettings);
    }

    public MultiBooleanSetting.Value get(int index) {
        return this.booleanSettings.get(index);
    }

    public boolean isEnable(String name) {
        MultiBooleanSetting.Value setting = this.getValueByName(name);
        return setting != null && setting.isEnabled();
    }

    public boolean isEnable(int index) {
        if (index >= this.getBooleanSettings().size()) {
            return false;
        } else {
            MultiBooleanSetting.Value setting = this.get(index);
            return setting != null && setting.isEnabled();
        }
    }

    public List<MultiBooleanSetting.Value> getSelectedValues() {
        return this.booleanSettings.stream().filter(MultiBooleanSetting.Value::isEnabled).collect(Collectors.toList());
    }

    public List<String> getSelectedNames() {
        return this.booleanSettings.stream().filter(MultiBooleanSetting.Value::isEnabled).map(MultiBooleanSetting.Value::getName).collect(Collectors.toList());
    }

    @Override
    public void safe(JsonObject propertiesObject) {
        StringBuilder builder = new StringBuilder();
        int j = 0;

        for (MultiBooleanSetting.Value s : this.getBooleanSettings()) {
            if (this.getValueByName(s.getName()).isEnabled()) {
                builder.append(s.getName()).append("\n");
            }

            j++;
        }

        propertiesObject.addProperty(this.getName(), builder.toString());
    }

    @Override
    public void load(JsonObject propertiesObject) {
        this.getBooleanSettings().forEach(booleanSettingx -> booleanSettingx.setEnabled(false));
        String[] strs = propertiesObject.get(String.valueOf(this.name)).getAsString().split("\n");

        for (String str : strs) {
            MultiBooleanSetting.Value booleanSetting = this.getValueByName(str);
            if (booleanSetting != null) {
                this.getValueByName(str).setEnabled(true);
            }
        }
    }

    @Generated
    public List<MultiBooleanSetting.Value> getBooleanSettings() {
        return this.booleanSettings;
    }

    public static class Value {
        private boolean enabled;
        private final String name;

        public Value(String name, boolean state) {
            this.enabled = state;
            this.name = name;
        }

        public Value(MultiBooleanSetting parent, String name, boolean state) {
            this.enabled = state;
            this.name = name;
            parent.booleanSettings.add(this);
        }

        public static MultiBooleanSetting.Value of(String name, boolean state) {
            return new MultiBooleanSetting.Value(name, state);
        }

        public static MultiBooleanSetting.Value of(String name) {
            return new MultiBooleanSetting.Value(name, true);
        }

        public void toggle() {
            this.enabled = !this.enabled;
        }

        @Generated
        public boolean isEnabled() {
            return this.enabled;
        }

        @Generated
        public String getName() {
            return this.name;
        }

        @Generated
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }
}
