package be.iminds.ilabt.jfed.ui.commandline.probe;

import be.iminds.ilabt.jfed.CorePreferencesModule;
import be.iminds.ilabt.jfed.MockHttpRepliesTestCoreModule;
import be.iminds.ilabt.jfed.TestAuthoritiesModule;
import be.iminds.ilabt.jfed.lowlevel.JFedException;
import be.iminds.ilabt.jfed.lowlevel.TestCertHelper;
import be.iminds.ilabt.jfed.lowlevel.connection.MockReplyLibrary;
import be.iminds.ilabt.jfed.ui.commandline.BaseCli;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.testng.annotations.Test;

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

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

public class CommandLineClientTest {
    private final TestCertHelper testCertHelper = new TestCertHelper();

    private File writeTmpFile(String name, String suffix, String content) throws IOException {
        File file = File.createTempFile(name, suffix);
        FileWriter fw = new FileWriter(file);
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(content);
        bw.close();
        file.deleteOnExit();
        return file;
    }

    private BaseCli getTestBaseCli() {
        return new BaseCli(System.err) {
            @Override
            public Injector getInjector(final PrintStream err, AbstractModule... extraModules) {
                assert userModule != null;
                assert authoritiesModule != null;
                if (userModule == null)
                    throw new RuntimeException("Bug in CLI implementation: userModule was not initialised.");
                if (authoritiesModule == null)
                    throw new RuntimeException("Bug in CLI implementation: authoritiesModule was not initialised.");

                MockHttpRepliesTestCoreModule testCoreModule =  new MockHttpRepliesTestCoreModule(testCertHelper);
                List<AbstractModule> mods = new ArrayList();
                mods.addAll(Arrays.asList(extraModules));
                mods.addAll(Arrays.asList(userModule, testCoreModule, new CorePreferencesModule(), new TestAuthoritiesModule()));
                if (testTargetModule != null)
                    mods.add(testTargetModule);

                MockReplyLibrary mockReplyLibrary = new MockReplyLibrary();
                testCoreModule.addMockReply(mockReplyLibrary.getVersion3());

                try {
                    Injector injector = Guice.createInjector(mods);
                    return injector;
                } catch (AssertionError e) {
                    handleInjectException(e, err);
                    return null;
                } catch (Exception e) {
                    handleInjectException(e, err);
                    return null;
                }
            }
        };
    }

    @Test
    public void testInvalidUserContextFile() throws IOException, JFedException {
        File contextFile = writeTmpFile("temp", ".properties", "testedAggregateManagerUrn = "+TestCertHelper.am1Urn+"\n");
        ByteArrayOutputStream outBaos = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(outBaos);
        ByteArrayOutputStream errBaos = new ByteArrayOutputStream();
        PrintStream err = new PrintStream(errBaos);
        byte[] inBytes = new byte[0];
        ByteArrayInputStream inBais = new ByteArrayInputStream(inBytes);
        InputStream in = inBais;

        String[] args = { "--api", "AMv2", "--context-file", contextFile.getAbsolutePath(), "GetVersion" };
        int ret = CommandLineClient.main_helper(args, out, err, in, getTestBaseCli(), false);
        out.close();
        err.close();

        String outStr = outBaos.toString("UTF-8");
        String errStr = errBaos.toString("UTF-8");

        System.out.println("out:"+outStr);
        System.out.println("err:"+errStr);

        assertThat(errStr, anyOf(
                containsString("property \"userAuthorityUrn\" is missing"),
                containsString("property \"username\" is missing"),
                containsString("property \"pemKeyAndCertFilename\" is missing")
        ));
        assertThat(ret, equalTo(1));
    }

    @Test
    public void testInvalidTargetContextFile() throws IOException, JFedException {
        File userFile = writeTmpFile("temp", ".pem", testCertHelper.getUserPem());

        File contextFile = writeTmpFile("temp", ".properties",
                "pemKeyAndCertFilename = "+userFile.getAbsolutePath()+"\n"+
                        "userAuthorityUrn = "+TestCertHelper.am1Urn+"\n"+
                        "username = tester\n");
        ByteArrayOutputStream outBaos = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(outBaos);
        ByteArrayOutputStream errBaos = new ByteArrayOutputStream();
        PrintStream err = new PrintStream(errBaos);
        byte[] inBytes = new byte[0];
        ByteArrayInputStream inBais = new ByteArrayInputStream(inBytes);
        InputStream in = inBais;

        String[] args = { "--api", "AMv2", "--context-file", contextFile.getAbsolutePath(), "GetVersion" };
        int ret = CommandLineClient.main_helper(args, out, err, in, getTestBaseCli(), false);
        out.close();
        err.close();

        String outStr = outBaos.toString("UTF-8");
        String errStr = errBaos.toString("UTF-8");

        System.out.println("out:"+outStr);
        System.out.println("err:"+errStr);

        assertThat(errStr, containsString("property \"testedAggregateManagerUrn\" or \"testedAggregateManagerUrnToConnect\" is missing"));
        assertThat(ret, equalTo(1));
    }

    @Test
    public void testContextFileGetVersion2() throws IOException, JFedException {
        File userFile = writeTmpFile("temp", ".pem", testCertHelper.getUserPem());

        File contextFile = writeTmpFile("temp", ".properties",
                "pemKeyAndCertFilename = "+userFile.getAbsolutePath().replace("\\", "\\\\")+"\n"+
                        "userAuthorityUrn = "+TestCertHelper.am1Urn+"\n"+
                        "username = tester\n"+
                        "testedAggregateManagerUrn = "+TestCertHelper.am1Urn+"\n");
        ByteArrayOutputStream outBaos = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(outBaos);
        ByteArrayOutputStream errBaos = new ByteArrayOutputStream();
        PrintStream err = new PrintStream(errBaos);
        byte[] inBytes = new byte[0];
        ByteArrayInputStream inBais = new ByteArrayInputStream(inBytes);
        InputStream in = inBais;

        String[] args = { "--api", "AMv2", "--context-file", contextFile.getAbsolutePath(), "GetVersion" };
        int ret = CommandLineClient.main_helper(args, out, err, in, getTestBaseCli(), false);
        out.close();
        err.close();

        String outStr = outBaos.toString("UTF-8");
        String errStr = errBaos.toString("UTF-8");

        System.out.println("out:"+outStr);
        System.out.println("err:"+errStr);

        assertThat(errStr, containsString("has no URL for AMv2"));
        assertThat(ret, equalTo(1));
    }

    @Test
    public void testContextFileGetVersion3() throws IOException, JFedException {
        File userFile = writeTmpFile("temp", ".pem", testCertHelper.getUserPem());

        File contextFile = writeTmpFile("temp", ".properties",
                "pemKeyAndCertFilename = "+userFile.getAbsolutePath().replace("\\", "\\\\")+"\n"+
                        "userAuthorityUrn = "+TestCertHelper.am1Urn+"\n"+
                        "username = tester\n"+
                        "testedAggregateManagerUrn = "+TestCertHelper.am1Urn+"\n");
        ByteArrayOutputStream outBaos = new ByteArrayOutputStream();
        PrintStream out = new PrintStream(outBaos);
        ByteArrayOutputStream errBaos = new ByteArrayOutputStream();
        PrintStream err = new PrintStream(errBaos);
        byte[] inBytes = new byte[0];
        ByteArrayInputStream inBais = new ByteArrayInputStream(inBytes);
        InputStream in = inBais;

        String[] args = { "--api", "AMv3", "--context-file", contextFile.getAbsolutePath(), "GetVersion" };
        int ret = CommandLineClient.main_helper(args, out, err, in, getTestBaseCli(), false);
        out.close();
        err.close();

        String outStr = outBaos.toString("UTF-8");
        String errStr = errBaos.toString("UTF-8");

        System.out.println("out:"+outStr);
        System.out.println("err:"+errStr);

        assertThat(outStr, containsString("\"VersionInfo\" : {\n" +
                "    \"api\" : \"3\""));
        assertThat(ret, equalTo(0));
    }
}
