package be.isach.ultracosmetics.util;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
public class CustomConfiguration extends YamlConfiguration {
private Map<String, List<String>> comments = null;
private boolean newLineAfterHeader = false;
private boolean newLinePerKey = false;
private CustomConfiguration() {
super();
this.comments = new LinkedHashMap<>();
}
public void addDefault(String path, Object defaultValue, String... comments) {
if (!contains(path))
set(path, defaultValue, comments);
}
public ConfigurationSection createSection(String path, String... comments) {
if (path != null && comments != null && comments.length > 0) {
List<String> commentsList = new ArrayList<>();
for (String comment : comments) {
if (comment != null) commentsList.add(comment);
else commentsList.add("");
}
this.comments.put(path, commentsList);
}
return super.createSection(path);
}
@Override
public void addDefault(String path, Object value) {
if (!contains(path))
set(path, value);
}
@Override
public void load(File file) throws IOException, InvalidConfigurationException {
super.load(file);
BufferedReader configReader = null;
List<String> configLines = new ArrayList<>();
try {
configReader = new BufferedReader(new FileReader(file));
String configReadLine;
while ((configReadLine = configReader.readLine()) != null) configLines.add(configReadLine);
} finally {
if (configReader != null) configReader.close();
}
boolean hasHeader = configLines.size() < 2 || !trim(configLines.get(1)).isEmpty();
Map<String, List<String>> configComments = new LinkedHashMap<>();
for (int lineIndex = 0; lineIndex < configLines.size(); lineIndex++) {
String configLine = configLines.get(lineIndex);
String trimmedLine = trimPrefixSpaces(configLine);
if (trimmedLine.startsWith("#") && (lineIndex > 0 || !hasHeader)) {
String configKey = getPathToComment(configLines, lineIndex, configLine);
if (configKey != null) {
List<String> keyComments = configComments.get(configKey);
if (keyComments == null) keyComments = new ArrayList<>();
keyComments.add(trimmedLine.substring(trimmedLine.startsWith("# ") ? 2 : 1));
configComments.put(configKey, keyComments);
}
}
}
comments = configComments;
}
public void load(File file, boolean loadComments) throws IOException, InvalidConfigurationException {
if (loadComments) this.load(file);
else super.load(file);
}
@Override
public void save(File file) throws IOException {
super.save(file);
List<String> configContent = new ArrayList<>();
BufferedReader configReader = null;
try {
configReader = new BufferedReader(new FileReader(file));
String configReadLine;
while ((configReadLine = configReader.readLine()) != null) configContent.add(configReadLine);
} finally {
if (configReader != null) configReader.close();
}
BufferedWriter configWriter = null;
try {
configWriter = new BufferedWriter(new FileWriter(file));
configWriter.write("");
for (int lineIndex = 0; lineIndex < configContent.size(); lineIndex++) {
String configLine = configContent.get(lineIndex);
String configKey = null;
if (!configLine.startsWith("#") && configLine.contains(":"))
configKey = getPathToKey(configContent, lineIndex, configLine);
if (configKey != null && this.comments.containsKey(configKey)) {
int numOfSpaces = getPrefixSpaceCount(configLine);
String spacePrefix = "";
for (int i = 0; i < numOfSpaces; i++) spacePrefix += " ";
List<String> configComments = this.comments.get(configKey);
if (configComments != null) {
for (String comment : configComments) {
configWriter.append(spacePrefix).append("# ").append(comment);
configWriter.newLine();
}
}
}
configWriter.append(configLine);
configWriter.newLine();
boolean isComment = configLine.startsWith("#");
if (this.newLineAfterHeader && lineIndex == 0 && isComment) {
configWriter.newLine();
} else if (this.newLinePerKey && lineIndex < configContent.size() - 1 && !isComment) {
String nextConfigLine = configContent.get(lineIndex + 1);
if (nextConfigLine != null && !nextConfigLine.startsWith(" ")) {
if (!nextConfigLine.startsWith("'") && !nextConfigLine.startsWith("-")) configWriter.newLine();
}
}
}
} finally {
if (configWriter != null) configWriter.close();
}
}
public void set(String key, Object value, String... comments) {
if (value != null) {
if (comments != null) {
if (comments.length > 0) {
List<String> commentsList = new ArrayList<>();
for (String comment : comments) {
if (comment != null) commentsList.add(comment);
else commentsList.add("");
}
this.comments.put(key, commentsList);
} else {
this.comments.remove(key);
}
}
} else {
this.comments.remove(key);
}
super.set(key, value);
}
public static CustomConfiguration loadConfiguration(File file) {
CustomConfiguration config = new CustomConfiguration();
try {
config.load(file);
} catch (FileNotFoundException ignored) {
} catch (IOException | InvalidConfigurationException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex);
}
return config;
}
private static String getPathToComment(List<String> configContents, int lineIndex, String configLine) {
if (configContents != null && lineIndex >= 0 && lineIndex < configContents.size() - 1 && configLine != null) {
String trimmedConfigLine = trimPrefixSpaces(configLine);
if (trimmedConfigLine.startsWith("#")) {
int currentIndex = lineIndex;
while (currentIndex < configContents.size() - 1) {
currentIndex++;
String currentLine = configContents.get(currentIndex);
String trimmedCurrentLine = trimPrefixSpaces(currentLine);
if (!trimmedCurrentLine.startsWith("#")) {
if (trimmedCurrentLine.contains(":")) {
return getPathToKey(configContents, currentIndex, currentLine);
} else {
break;
}
}
}
}
}
return null;
}
private static String getPathToKey(List<String> configContents, int lineIndex, String configLine) {
if (configContents != null && lineIndex >= 0 && lineIndex < configContents.size() && configLine != null) {
if (!configLine.startsWith("#") && configLine.contains(":")) {
int spacesBeforeKey = getPrefixSpaceCount(configLine);
String key = trimPrefixSpaces(configLine.substring(0, configLine.indexOf(':')));
if (spacesBeforeKey > 0) {
int currentIndex = lineIndex;
int previousSpacesBeforeCurrentLine = -1;
boolean atZeroSpaces = false;
while (currentIndex > 0) {
currentIndex--;
String currentLine = configContents.get(currentIndex);
int spacesBeforeCurrentLine = getPrefixSpaceCount(currentLine);
if (trim(currentLine).isEmpty()) break;
if (!trim(currentLine).startsWith("#")) {
if (spacesBeforeCurrentLine < spacesBeforeKey) {
if (currentLine.contains(":")) {
if (spacesBeforeCurrentLine > 0 || !atZeroSpaces) {
if (spacesBeforeCurrentLine == 0) atZeroSpaces = true;
if (previousSpacesBeforeCurrentLine == -1 || spacesBeforeCurrentLine < previousSpacesBeforeCurrentLine) {
previousSpacesBeforeCurrentLine = spacesBeforeCurrentLine;
key = trimPrefixSpaces(currentLine.substring(0, currentLine.indexOf(":"))) + "." + key;
}
} else {
break;
}
}
}
}
}
}
return key;
}
}
return null;
}
private static int getPrefixSpaceCount(String aString) {
int spaceCount = 0;
if (aString != null && aString.contains(" ")) {
for (char aCharacter : aString.toCharArray()) {
if (aCharacter == ' ') spaceCount++;
else break;
}
}
return spaceCount;
}
private static String trim(String aString) {
return aString != null ? aString.trim().replace(System.lineSeparator(), "") : "";
}
private static String trimPrefixSpaces(String aString) {
if (aString != null) {
while (aString.startsWith(" ")) aString = aString.substring(1);
}
return aString;
}
}