package be.iminds.ilabt.jfed.ui.cli;

import org.apache.commons.cli.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.testng.Assert.*;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import static org.mockito.Mockito.mock;

public class ExperimenterCliTest {

    @org.testng.annotations.Test
    public void testExtractCredentialsOneA() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = c1;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsOneB() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }
    @org.testng.annotations.Test
    public void testExtractCredentialsOneC() throws Exception {
        String sc = "signed-credential";
        String sc1 = "somenamespace:"+sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = c1;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsOneD() throws Exception {
        String sc = "signed-credential";
        String sc1 = "somenamespace-2:"+sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }
    @org.testng.annotations.Test
    public void testExtractCredentialsOneE() throws Exception {
        String sc = "signed-credential";
        String sc1 = "_somenamespace-2:"+sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsOneF() throws Exception {
        String sc = "signed-credential";
        String sc1 = "\uFFFDsome_\u1FFFNAME\u00B7space.\u036F-2:"+sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsTwoA() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = c1+c2;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsTwoB() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f+c2+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }
    @org.testng.annotations.Test
    public void testExtractCredentialsTwoC() throws Exception {
        String sc = "signed-credential";
        String sc1 = "somenamespace-1:"+sc;
        String sc2 = "somenamespace-2:"+sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = c1+c2;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsTwoD() throws Exception {
        String sc = "signed-credential";
        String sc1 = "somenamespace-2:"+sc;
        String sc2 = sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f+c2+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsTwoE() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = "somenamespace-2:"+sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f+c2+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsTwoF() throws Exception {
        String sc = "signed-credential";
        String sc1 = "somenamespace-SAME:"+sc;
        String sc2 = "somenamespace-SAME:"+sc;
        String sc3 = sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f+c2+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsThreeA() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = "somenamespace-23:"+sc;
        String sc3 = "somenamespace-23:"+sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = c1+c2+c3;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        expected.add(c3);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testExtractCredentialsThreeB() throws Exception {
        String sc = "signed-credential";
        String sc1 = sc;
        String sc2 = "somenamespace-23:"+sc;
        String sc3 = "somenamespace-23:"+sc;
        String f = "<bla>fff</bla>";
        String f1 = "<bla>bla</bla>";
        String f2 = "<bla>blabla</bla>";
        String f3 = "<bla>blablabla</bla>";
        String c1 = "<"+sc1+">"+f1+"</"+sc1+">";
        String c2 = "<"+sc2+">"+f2+"</"+sc2+">";
        String c3 = "<"+sc3+">"+f3+"</"+sc3+">";
        String multiCredentialString = f+c1+f+c2+f+c3+f;

        List<String> expected = new ArrayList<>();
        expected.add(c1);
        expected.add(c2);
        expected.add(c3);
        List<String> actual = ExperimenterCli.extractCredentials(multiCredentialString);

        assertThat(actual, is(notNullValue()));
        assertThat(actual, hasSize(expected.size()));
        assertThat(actual, is(equalTo(expected)));
    }

    @org.testng.annotations.Test
    public void testCliArg() throws Exception {
        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("test")
                .withDescription("Test")
                .hasArg()
                .withArgName("TEST")
                .create());

        CommandLineParser parser = new BasicParser();
        String[] args = new String[2];
        args[0] = "--test";
        args[1] = "SUCCESS";
        CommandLine line = parser.parse(options, args);

        assertThat(line.hasOption("test"), is(true));
        assertThat(line.getOptionValue("test"), is(equalTo(args[1])));
    }

    @org.testng.annotations.Test
    public void testCliMultiArg() throws Exception {
        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("test")
                .withDescription("Test")
                .hasArg()
                .withArgName("TEST")
                .create());

        CommandLineParser parser = new BasicParser();
        String[] args = new String[4];
        args[0] = "--test";
        args[1] = "SUCCESS";
        args[2] = "--test";
        args[3] = "SUCCESS2";
        CommandLine line = parser.parse(options, args);

        assertThat(line.hasOption("test"), is(true));
        String [] actual = line.getOptionValues("test");
        assertThat(actual.length, is(equalTo(2)));
        assertThat(actual[0], is(equalTo(args[1])));
        assertThat(actual[1], is(equalTo(args[3])));
    }

    @org.testng.annotations.Test
    public void testCliArgs() throws Exception {
        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("test")
                .withDescription("Test")
                .hasArgs(2)
                .create());

        CommandLineParser parser = new BasicParser();
        String[] args = new String[3];
        args[0] = "--test";
        args[1] = "ONE";
        args[2] = "TWO";
        CommandLine line = parser.parse(options, args);

        assertThat(line.hasOption("test"), is(true));
        System.out.println("test=" + Arrays.asList(line.getOptionValues("test")));
        assertThat(line.getOptionValue("test"), is(equalTo(args[1])));
    }

    //hasArgs(2) doesn't work like I would want  (--test <A> <B> is the same as --test <A> --test <B> and it should not be.)

//    @org.testng.annotations.Test(expectedExceptions = { ParseException.class })
//    public void testCliArgsBad() throws Exception {
//        Options options = new Options();
//        options.addOption(OptionBuilder.withLongOpt("test")
//                .withDescription("Test")
//                .hasArgs(2)
//                .create());
//
//        CommandLineParser parser = new BasicParser();
//        String[] args = new String[2];
//        args[0] = "--test";
//        args[1] = "ONE";
//        CommandLine line = parser.parse(options, args);
//
//        assertThat(line.hasOption("test"), is(true));
//        System.out.println("test=" + Arrays.asList(line.getOptionValues("test")));
//    }
//
//    @org.testng.annotations.Test(expectedExceptions = { ParseException.class })
//    public void testCliArgsBad2() throws Exception {
//        Options options = new Options();
//        options.addOption(OptionBuilder.withLongOpt("test")
//                .withDescription("Test")
//                .hasArgs(2)
//                .create());
//
//        CommandLineParser parser = new BasicParser();
//        String[] args = new String[4];
//        args[0] = "--test";
//        args[1] = "ONE";
//        args[2] = "TWO";
//        args[3] = "BAD";
//        CommandLine line = parser.parse(options, args);
//
//        assertThat(line.hasOption("test"), is(true));
//        System.out.println("test=" + Arrays.asList(line.getOptionValues("test")));
//    }
//
//    @org.testng.annotations.Test(expectedExceptions = { ParseException.class })
//    public void testCliArgsBad3() throws Exception {
//        Options options = new Options();
//        options.addOption(OptionBuilder.withLongOpt("test")
//                .withDescription("Test")
//                .hasArgs(2)
//                .create());
//
//        CommandLineParser parser = new BasicParser();
//        String[] args = new String[6];
//        args[0] = "--test";
//        args[1] = "ONE";
//        args[2] = "TWO";
//        args[3] = "BAD";
//        args[4] = "--test";
//        args[5] = "FOUR";
//        CommandLine line = parser.parse(options, args);
//
//        assertThat(line.hasOption("test"), is(true));
//        System.out.println("test=" + Arrays.asList(line.getOptionValues("test")));
//    }

    @org.testng.annotations.Test
    public void testCliMultiArgs() throws Exception {
        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("test")
                .withDescription("Test")
                .hasArgs(2)
                .create());

        CommandLineParser parser = new BasicParser();
        String[] args = new String[6];
        args[0] = "--test";
        args[1] = "ONE";
        args[2] = "TWO";
        args[3] = "--test";
        args[4] = "THREE";
        args[5] = "FOUR";
        CommandLine line = parser.parse(options, args);

        assertThat(line.hasOption("test"), is(true));
        System.out.println("test=" + Arrays.asList(line.getOptionValues("test")));
        assertThat(line.getOptionValue("test"), is(equalTo(args[1])));
    }
}