package com.spaceapplications.yamcs.scpi;

import static pl.touk.throwing.ThrowingFunction.unchecked;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;

public class Config {
  public Daemon daemon = new Daemon();
  public List<Device> decices = Arrays.asList();

  public static class Daemon {
    public int port;
    public int max_connections;
  }

  public static class Device {
    public String name = "";
  }

  public static Config load(String path) {
    Constructor c = new Constructor(Config.class);
    TypeDescription d = new TypeDescription(Config.class);
    d.putListPropertyType("devices", Device.class);
    c.addTypeDescription(d);
    Yaml yaml = new Yaml(c);
    InputStream is = unchecked(Config::inputStream).apply(path);

    try {
      Config config = (Config) yaml.load(is);
      if (config == null)
        throw loadException("The file is empty.", path);
      return config;
    } catch (YAMLException e) {
      throw loadException("Expecting the file to have the following format: \n{1}", path, exampleYamlConfig());
    }
  }

  private static RuntimeException loadException(String msg, Object... args) {
    String baseMsg = "Error loading config file \"{0}\". ";
    msg = MessageFormat.format(baseMsg + msg, args);
    throw new RuntimeException(msg);
  }

  private static String exampleYamlConfig() {
    DumperOptions opts = new DumperOptions();
    opts.setPrettyFlow(true);
    Yaml yaml = new Yaml(opts);
    String example = yaml.dump(new Config());
    String exampleWithoutTag = example.replaceAll("^(.*)\n", "");
    return exampleWithoutTag;
  }

  private static InputStream inputStream(String path) throws IOException {
    Path p = Paths.get("config.yaml");
    return Files.newInputStream(p);
  }
}
@@ -568,16 +568,22 @@
 c Daemon
+Config
  daemon 
@@ -594,16 +594,22 @@
 w Daemon
+Config
 ();%0A  pu
@@ -624,16 +624,22 @@
 t%3CDevice
+Config
 %3E decice
@@ -688,16 +688,22 @@
 s Daemon
+Config
  %7B%0A    p
@@ -783,16 +783,22 @@
 s Device
+Config
  %7B%0A    p
@@ -1022,16 +1022,22 @@
 , Device
+Config
 .class);

Add Config suffix to config sub-objects