package picocli;

import java.io.File;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.Callable;

import org.junit.Test;
import picocli.CommandLine.Command;
import picocli.CommandLine.IParameterPreprocessor;
import picocli.CommandLine.Model.ArgSpec;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;

import static org.junit.Assert.*;

public class Issue1125_1538_OptionNameOrSubcommandAsOptionValue {
    @Command(name = "mycommand")
    static class MyCommand implements Callable<Integer> {

        @Option(names = "-output", preprocessor = MyPreprocessor.class)
        File output = new File(".");

        static class MyPreprocessor implements IParameterPreprocessor {
            public boolean preprocess(Stack<String> args, CommandSpec commandSpec, ArgSpec argSpec, Map<String, Object> info) {
                if (args.isEmpty()) {
                    throw new ParameterException(commandSpec.commandLine(), "Error: option '-output' requires a parameter");
                }
                String arg = args.pop();
                //System.err.printf("Setting %s to '%s'%n", argSpec, arg);
                argSpec.setValue(new File(arg));
                return true;
            }
        }

        public Integer call() {
            return 11;
        }

        @Command(name = "mySubcommand")
        public int mySubcommand() {
            return 13;
        }
    }

    @Test
    public void testSubcommandAsOptionName() {
        MyCommand obj = new MyCommand();
        CommandLine cmdLine = new CommandLine(obj);
        int exitCode = cmdLine.execute("-output", "abc", "mySubcommand");
        assertEquals(13, exitCode);
        assertEquals("abc", obj.output.getName());

        exitCode = cmdLine.execute("-output=mySubcommand", "mySubcommand");
        assertEquals(13, exitCode);
        assertEquals("mySubcommand", obj.output.getName());

        exitCode = cmdLine.execute("-output", "mySubcommand", "mySubcommand");
        assertEquals(13, exitCode);
        assertEquals("mySubcommand", obj.output.getName());
    }
}

@@ -134,20 +134,100 @@
 g.junit.
-Test
+Rule;%0Aimport org.junit.Test;%0Aimport org.junit.contrib.java.lang.system.SystemErrRule
 ;%0Aimport
@@ -579,16 +579,127 @@
 Value %7B%0A
+%0A    @Rule%0A    public SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests();%0A%0A
     @Com
@@ -1484,32 +1484,113 @@
    %7D%0A        %7D%0A%0A
+        @Option(names = %22-x%22) String x;%0A        @Option(names = %22-y%22) String y;%0A%0A
         public I
@@ -2347,32 +2347,32 @@
 (13, exitCode);%0A
-
         assertEq
@@ -2420,11 +2420,667 @@
 );%0A    %7D
+%0A%0A    @Test%0A    public void testAmbiguousOptions() %7B%0A        //-x -y=123%0A        MyCommand obj = new MyCommand();%0A        CommandLine cmdLine = new CommandLine(obj);%0A        int exitCode = cmdLine.execute(%22-x%22, %22-y=123%22);%0A        assertEquals(2, exitCode);%0A        String expected = String.format(%22Expected parameter for option '-x' but found '-y=123'%25n%22 +%0A            %22Usage: mycommand %5B-output=%3Coutput%3E%5D %5B-x=%3Cx%3E%5D %5B-y=%3Cy%3E%5D %5BCOMMAND%5D%25n%22 +%0A            %22      -output=%3Coutput%3E%25n%22 +%0A            %22  -x=%3Cx%3E%25n%22 +%0A            %22  -y=%3Cy%3E%25n%22 +%0A            %22Commands:%25n%22 +%0A            %22  mySubcommand%25n%22);%0A        assertEquals(expected, systemErrRule.getLog());%0A    %7D
 %0A%7D%0A

add test