package xyz.upperlevel.uppercore.config.parser;

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import xyz.upperlevel.uppercore.config.exceptions.WrongNodeTypeConfigException;

import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Collection;

public abstract class ConfigParser {
    public static Yaml defaultYaml = new Yaml();

    private final Type handleType;

    public ConfigParser(Type handleType) {
        this.handleType = handleType;
    }

    public abstract Object parse(Node root);

    public Object parse(Reader reader) {
        return parse(defaultYaml.compose(reader));
    }

    public Type getHandleClass() {
        return handleType;
    }

    // ---------------- Helper methods ----------------

    public static void checkTag(Node node, Tag expected) {
        if (node.getTag() != expected) {
            throw new WrongNodeTypeConfigException(node, expected);
        }
    }

    public static void checkTag(Node node, Collection<Tag> expected) {
        if (!expected.contains(node.getTag())) {
            throw new WrongNodeTypeConfigException(node, expected.toArray(new Tag[0]));
        }
    }

    public static void checkNodeId(Node node, NodeId expectedId) {
        if (expectedId != node.getNodeId()) {
            throw new WrongNodeTypeConfigException(node, expectedId);
        }
    }

    public static void checkNodeId(Node node, Collection<NodeId> expectedIds) {
        if (!expectedIds.contains(node.getNodeId())) {
            throw new WrongNodeTypeConfigException(node, expectedIds.toArray(new NodeId[0]));
        }
    }

    public static ScalarNode replaceValue(ScalarNode original, String newValue) {
        return new ScalarNode(original.getTag(), true, newValue, original.getStartMark(),
                original.getEndMark(), original.getStyle());
    }
}

@@ -42,16 +42,57 @@
 arser;%0A%0A
+import org.yaml.snakeyaml.DumperOptions;%0A
 import o
@@ -399,173 +399,819 @@
 ang.
-reflect.Type;%0Aimport java.util.Collection;%0A%0Apublic abstract class ConfigParser %7B%0A    public static Yaml defaultYaml = new Yaml();%0A%0A    private final Type handleType;
+invoke.LambdaMetafactory;%0Aimport java.lang.invoke.MethodHandle;%0Aimport java.lang.invoke.MethodHandles;%0Aimport java.lang.reflect.Field;%0Aimport java.lang.reflect.Type;%0Aimport java.util.Collection;%0A%0Apublic abstract class ConfigParser %7B%0A    public static Yaml defaultYaml = new Yaml();%0A    private static final MethodHandle styleGetter;%0A%0A    private final Type handleType;%0A%0A    static %7B%0A        try %7B%0A            Field reflectedField = ScalarNode.class.getDeclaredField(%22style%22);%0A            reflectedField.setAccessible(true);%0A            final MethodHandles.Lookup lookup = MethodHandles.lookup();%0A            styleGetter = lookup.unreflectGetter(reflectedField);%0A        %7D catch (Exception e) %7B%0A            throw new RuntimeException(%22Cannot initialize style getter for snakeyaml ScalarNode%22, e);%0A        %7D%0A    %7D
 %0A%0A  
@@ -2501,24 +2501,277 @@
 newValue) %7B%0A
+        DumperOptions.ScalarStyle style;%0A        try %7B%0A            style = (DumperOptions.ScalarStyle) styleGetter.invokeExact(original);%0A        %7D catch (Throwable t) %7B%0A            throw new RuntimeException(%22Cannot invoke style getter%22, t);%0A        %7D%0A
         retu
@@ -2851,24 +2851,8 @@
 k(),
-%0A               
  ori
@@ -2875,27 +2875,13 @@
 (), 
-original.getS
+s
 tyle
-()
 );%0A 

Fix snakeYaml no getStyle method