package com.github.sormuras.bach.command;

import java.util.List;
import java.util.Optional;

/**
 * The javac command reads Java declarations and compiles them into class files.
 *
 * @param release Compile source code according to the rules of the Java programming language for
 *     the specified Java SE release, generating class files which target that release.
 * @param modules Compiles those source files in the named modules that are newer than the
 *     corresponding files in the output directory.
 * @param verbose Outputs messages about what the compiler is doing. Messages include information
 *     about each class loaded and each source file compiled.
 * @param additionals Aggregates additional command-line arguments.
 */
public record JavacCommand(
    ReleaseOption release,
    ModulesOption modules,
    VerboseOption verbose,
    AdditionalArgumentsOption additionals)
    implements Command<JavacCommand> {

  public JavacCommand() {
    this(
        ReleaseOption.empty(),
        ModulesOption.empty(),
        VerboseOption.empty(),
        AdditionalArgumentsOption.empty());
  }

  @Override
  public String name() {
    return "javac";
  }

  @Override
  public JavacCommand option(Option option) {
    return new JavacCommand(
        option instanceof ReleaseOption release ? release : release,
        option instanceof ModulesOption modules ? modules : modules,
        option instanceof VerboseOption verbose ? verbose : verbose,
        option instanceof AdditionalArgumentsOption additionals ? additionals : additionals);
  }

  public JavacCommand release(Integer release) {
    return option(new ReleaseOption(Optional.ofNullable(release)));
  }

  @Override
  public JavacCommand additionals(AdditionalArgumentsOption additionals) {
    return option(additionals);
  }

  public JavacCommand modules(String... modules) {
    return option(new ModulesOption(List.of(modules)));
  }

  public JavacCommand verbose(Boolean verbose) {
    return option(new VerboseOption(Optional.ofNullable(verbose)));
  }

  @Override
  public List<String> toArguments() {
    var javac = Command.of(name());
    if (release.isPresent()) javac = javac.add("--release", release.get());
    if (modules.isPresent()) javac = javac.add("--module", modules.join(","));
    if (verbose.isTrue()) javac = javac.add("--verbose");
    javac = javac.addAll(additionals.values());
    return javac.toArguments();
  }

  /** Java SE release feature version option. */
  public record ReleaseOption(Optional<Integer> value) implements Option.Value<Integer> {
    public static ReleaseOption empty() {
      return new ReleaseOption(Optional.empty());
    }
  }
}

@@ -1687,132 +1687,8 @@
  %7D%0A%0A
-  @Override%0A  public JavacCommand additionals(AdditionalArgumentsOption additionals) %7B%0A    return option(additionals);%0A  %7D%0A%0A
   pu
@@ -1730,24 +1730,24 @@
  modules) %7B%0A
+
     return o
@@ -1909,32 +1909,156 @@
 erbose)));%0A  %7D%0A%0A
+  @Override%0A  public JavacCommand additionals(AdditionalArgumentsOption additionals) %7B%0A    return option(additionals);%0A  %7D%0A%0A
   @Override%0A  pu
@@ -2340,16 +2340,23 @@
 bose%22);%0A
+    //%0A
     java
@@ -2391,24 +2391,31 @@
 .values());%0A
+    //%0A
     return j

Align method ordering to component/arguments ordering