package picocli.codegen.aot.graalvm;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Parameters;
import picocli.CommandLine.Spec;
import picocli.CommandLine.Unmatched;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;

/**
 * This command's `run` method uses an extra ResourceBundle with base="some.extra.bundle".
 * Make sure to add this to the native image with the ResourceConfigGenerator tool.
 */
@Command(name = "example",
        mixinStandardHelpOptions = true,
        subcommands = CommandLine.HelpCommand.class,
        resourceBundle = "picocli.codegen.aot.graalvm.exampleResources",
        version = {
                "Example " + CommandLine.VERSION,
                "JVM: ${java.version} (${java.vendor} ${java.vm.name} ${java.vm.version})",
                "OS: ${os.name} ${os.version} ${os.arch}"
        })
public class Example implements Runnable {

    @Command public static class ExampleMixin {

        @Option(names = "-l")
        int length;
    }

    @Option(names = "-t")
    final TimeUnit timeUnit = TimeUnit.SECONDS;

    @Parameters(index = "0")
    File file;

    @Spec
    CommandSpec spec;

    @Mixin
    ExampleMixin mixin;

    @Unmatched
    final List<String> unmatched = new ArrayList<String>();

    private int minimum;
    private List<File> otherFiles;

    @Command(resourceBundle = "picocli.codegen.aot.graalvm.exampleMultiplyResources")
    int multiply(@Option(names = "--count") int count,
                 @Parameters int multiplier) {
        System.out.println("Result is " + count * multiplier);
        return count * multiplier;
    }

    @Option(names = "--minimum")
    public void setMinimum(int min) {
        if (min < 0) {
            throw new ParameterException(spec.commandLine(), "Minimum must be a positive integer");
        }
        minimum = min;
    }

    @Parameters(index = "1..*")
    public void setOtherFiles(List<File> otherFiles) {
        for (File f : otherFiles) {
            if (!f.exists()) {
                throw new ParameterException(spec.commandLine(), "File " + f.getAbsolutePath() + " must exist");
            }
        }
        this.otherFiles = otherFiles;
    }

    public void run() {
        System.out.printf("timeUnit=%s, length=%s, file=%s, unmatched=%s, minimum=%s, otherFiles=%s%n",
                timeUnit, mixin.length, file, unmatched, minimum, otherFiles);
        System.out.println("Getting value from some.extra.bundle:");
        ResourceBundle bundle = ResourceBundle.getBundle("some.extra.bundle");
        System.out.println("Found bundle. Its value for 'key' is: " + bundle.getString("key"));
    }

    public static void main(String[] args) {
        new CommandLine(new Example()).execute(args);
    }
}

@@ -1245,138 +1245,499 @@
 %22-l%22
-)%0A        int length;%0A    %7D%0A%0A    @Option(names = %22-t%22)%0A    final TimeUnit timeUnit = TimeUnit.SECONDS;%0A%0A    @Parameters(index = %220
+, description = %22This option is the length option. It is not actually used anywhere. This option is mixed in to other commands.%22)%0A        int length;%0A    %7D%0A%0A    @Option(names = %22-t%22, description = %22This is a timeUnit option. Its default value is $%7BDEFAULT-VALUE%7D, valid values are $%7BCOMPLETION-CANDIDATES%7D.%22)%0A    final TimeUnit timeUnit = TimeUnit.SECONDS;%0A%0A    @Parameters(index = %220%22, description = %22This is a positional parameter at index 0. The value will be converted to a java.io.File.
 %22)%0A 
@@ -2281,16 +2281,132 @@
 minimum%22
+, description = %22This option demonstrates an @Option-annotated method. It can be used to validate the option value.%22
 )%0A    pu
@@ -2630,16 +2630,207 @@
 = %221..*%22
+, description = %22Positional parameters from index 1..* are captured in this annotated @Parameters method. It can be used to validate the values. Any specified value must be an existing file.%22
 )%0A    pu

add long descriptions to Example to test auto (terminal) width in native images