package org.jboss.installer.postinstall.task;

import io.undertow.Undertow;
import io.undertow.server.handlers.resource.PathResourceManager;
import org.apache.commons.io.FileUtils;
import org.jboss.installer.core.DatabaseDriver;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.postinstall.TaskPrinter;
import org.jboss.installer.test.utils.TestServer;
import org.junit.After;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static io.undertow.Handlers.resource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.jboss.installer.test.utils.TestServer.TARGET_PATH;

public class JDBCDriverModuleTaskTest {

    public static final String MODULE_XML = "module.xml";
    public static final String IBM_DB2_JAR = "ibm-db2.jar";
    public static final String IBM_DB2_JAR_COPY = "ibm-db2-copy.jar";
    @ClassRule
    public static ExternalResource testServer = new TestServer();
    private final Path pathToIBMDB2Jar = Path.of(
            JDBCDriverTaskTest.class.getClassLoader().getResource("jars").toURI()).toAbsolutePath();
    private Path pathToModuleXml;
    private Undertow server;
    private TaskPrinter printer = new NoopPrinter();

    public JDBCDriverModuleTaskTest() throws Exception {
    }

    @After
    public void deleteModuleDirectory() throws Exception {
        if (pathToModuleXml != null) {
            FileUtils.deleteDirectory(pathToModuleXml.toFile());
        }
        if (server != null) {
            server.stop();
        }
    }
    @Test
    public void addModuleTestWithLocalJar() {
        InstallationData iData = new InstallationData();
        iData.setTargetFolder(TARGET_PATH);
        List<String> jarList = Collections.singletonList(pathToIBMDB2Jar.resolve(IBM_DB2_JAR).toString());
        JDBCDriverTask.Config config = new JDBCDriverTask.Config(DatabaseDriver.IBM_DB2, jarList, Collections.emptyList());
        iData.putConfig(config);
        pathToModuleXml = TARGET_PATH.resolve(config.getDatabaseDriver().getDirectoryStructure());
        assertCreatedModuleFiles(iData, Collections.singletonList(IBM_DB2_JAR));
    }

    @Test
    public void addModuleTestWithRemoteJar() {
        InstallationData iData = new InstallationData();
        iData.setTargetFolder(TARGET_PATH);
        startLocalhost();
        List<String> jarList = Collections.singletonList("http://localhost:8123/" + IBM_DB2_JAR);
        JDBCDriverTask.Config config = new JDBCDriverTask.Config(DatabaseDriver.IBM_DB2, jarList, Collections.emptyList());
        iData.putConfig(config);
        pathToModuleXml = TARGET_PATH.resolve(config.getDatabaseDriver().getDirectoryStructure());
        assertCreatedModuleFiles(iData, Collections.singletonList(IBM_DB2_JAR));
    }

    @Test
    public void addModuleTestWithMultipleRemoteJar() throws IOException {
        InstallationData iData = new InstallationData();
        iData.setTargetFolder(TARGET_PATH);
        File copiedIbmJar = pathToIBMDB2Jar.resolve(IBM_DB2_JAR_COPY).toFile();
        FileUtils.copyFile(pathToIBMDB2Jar.resolve(IBM_DB2_JAR).toFile(), copiedIbmJar);
        Assert.assertTrue(copiedIbmJar.exists());
        startLocalhost();
        List<String> jarList = Arrays.asList(
                "http://localhost:8123/" + IBM_DB2_JAR,
                "http://localhost:8123/" + IBM_DB2_JAR_COPY);
        JDBCDriverTask.Config config = new JDBCDriverTask.Config(DatabaseDriver.IBM_DB2, jarList, Collections.emptyList());
        iData.putConfig(config);
        pathToModuleXml = TARGET_PATH.resolve(config.getDatabaseDriver().getDirectoryStructure());
        assertCreatedModuleFiles(iData, Arrays.asList(IBM_DB2_JAR, IBM_DB2_JAR_COPY));
    }

    private void startLocalhost() {
        server = Undertow.builder()
                .addHttpListener(8123, "localhost")
                .setHandler(resource(new PathResourceManager(pathToIBMDB2Jar, 100))
                        .setDirectoryListingEnabled(true))
                .build();
        server.start();
    }

    private void assertCreatedModuleFiles(InstallationData iData, List<String> jars) {
        Assert.assertTrue(new JDBCDriverModuleTask().applyToInstallation(iData, printer));
        Assert.assertTrue(pathToModuleXml.toFile().isDirectory());
        Assert.assertEquals(jars.size() + 1, pathToModuleXml.toFile().list().length);
        Assert.assertTrue(pathToModuleXml.resolve(MODULE_XML).toFile().exists());
        assertThat(pathToModuleXml.toFile().list()).containsAll(jars);
    }
}
