/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.meecrowave.maven;

import static java.util.Optional.ofNullable;
import static org.apache.ziplock.JarLocation.jarLocation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import javax.enterprise.inject.Model;

import org.apache.commons.io.IOUtils;
import org.apache.cxf.helpers.FileUtils;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.testing.MojoRule;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.meecrowave.io.IO;
import org.app.Endpoint;
import org.app.Injectable;
import org.app.RsApp;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.repository.LocalRepository;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;

public class MeecrowaveRunMojoTest {

	private static final int RETRY_COUNT = 1000;
	private static final int RETRY_WAIT_PERIOD = 500;

	private static byte[] additionalEndpointClass;

	@Rule
    public final MojoRule mojo = new MojoRule();

	private MavenProject project;
    private MavenSession session;
    private int port;
    private MojoExecution execution;

    @BeforeClass
    public static void removeAdditionalEndpointClass() throws Exception {
        File additionalEndpointClassFile = getAdditionalEndpointClass();
        try (InputStream classStream = new FileInputStream(additionalEndpointClassFile)) {
            additionalEndpointClass = IOUtils.toByteArray(classStream);
        }
        assumeTrue(additionalEndpointClassFile.delete());
    }

    @AfterClass
    public static void restoreAdditionalEndpointClass() throws Exception {
        IOUtils.write(additionalEndpointClass, new FileOutputStream(getAdditionalEndpointClass()));
    }

    private static File getAdditionalEndpointClass() throws URISyntaxException {
        return new File(new File(MeecrowaveRunMojoTest.class.getResource("/").toURI()), "org/app/AdditionalEndpoint.class");
    }

    @Before
	public void setupMojoExecution() throws Exception {
        final File moduleBase = jarLocation(MeecrowaveRunMojoTest.class).getParentFile().getParentFile();
        final File basedir = new File(moduleBase, "src/test/resources/" + getClass().getSimpleName());
        final File pom = new File(basedir, "pom.xml");
        final MavenExecutionRequest request = new DefaultMavenExecutionRequest();
        request.setBaseDirectory(basedir);
        final ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
        final DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(new File(moduleBase, "target/fake"), "")));
        configuration.setRepositorySession(repositorySession);
        project = mojo.lookup(ProjectBuilder.class).build(pom, configuration).getProject();
        session = mojo.newMavenSession(project);
        try (final ServerSocket serverSocket = new ServerSocket(0)) {
            port = serverSocket.getLocalPort();
        }
        execution = mojo.newMojoExecution("run");
	}

	@Test
    public void classpathDeployment() throws Exception {
        execution.getConfiguration().getChild("httpPort").setValue(Integer.toString(port));
        final Runnable quitCommand = quitCommand();
        final Thread mojoExecutor = mojoExecutor();
        try {
            mojoExecutor.start();
            retry(() -> {
            	assertEquals("simple", IOUtils.toString(new URL("http://localhost:" + port + "/api/test")));
            	assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("first_name"));
            	assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("last_name"));
            	assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("firstname"));
            	assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("null"));
            	assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/sub/index.html")).contains("<h1>yes</h1>"));
            	assertNotAvailable(new URL("http://localhost:" + port + "/api/additional"));
            	quitCommand.run();
            });
        } finally {
            mojoExecutor.join(TimeUnit.MINUTES.toMillis(1));
            if (mojoExecutor.isAlive()) {
                mojoExecutor.interrupt();
                fail("Runner didn't terminate properly");
            }
        }
    }

    @Test
    public void webappDeployment() throws Exception {
        File target = new File(MeecrowaveRunMojoTest.class.getResource("/").toURI()).getParentFile();
        File webappDirectory = new File(target, MeecrowaveRunMojoTest.class.getSimpleName());
        webappDirectory.mkdir();
        assertTrue(webappDirectory.exists());
        setupWebapp(webappDirectory);
        execution.getConfiguration().getChild("httpPort").setValue(Integer.toString(port));
        execution.getConfiguration().getChild("useClasspathDeployment").setValue("false");
        execution.getConfiguration().getChild("webapp").setValue(webappDirectory.getAbsolutePath());
        final Runnable quitCommand = quitCommand();
        final Thread mojoExecutor = mojoExecutor();
        try {
            mojoExecutor.start();
            retry(() -> {
                assertEquals("simple", IOUtils.toString(new URL("http://localhost:" + port + "/api/test")));
                assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("first_name"));
                assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("last_name"));
                assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("firstname"));
                assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/test/model")).contains("null"));
                assertTrue(IOUtils.toString(new URL("http://localhost:" + port + "/api/additional")).contains("available"));
                assertNotAvailable(new URL("http://localhost:" + port + "/sub/index.html"));
                quitCommand.run();
            });
        } finally {
            mojoExecutor.join(TimeUnit.MINUTES.toMillis(1));
            if (mojoExecutor.isAlive()) {
                mojoExecutor.interrupt();
                fail("Runner didn't terminate properly");
            }
        }
    }

    @Test
    public void autoreloadWithClasspathDeployment() throws Exception {
        File additionalEndpointFile = getAdditionalEndpointClass();
        execution.getConfiguration().getChild("httpPort").setValue(Integer.toString(port));
        execution.getConfiguration().getChild("watcherBouncing").setValue("1");
        Runnable quitCommand = quitCommand();
        final Thread mojoExecutor = mojoExecutor();
        try {
            mojoExecutor.start();
            retry(() -> {
                assertEquals("simple", IOUtils.toString(new URL("http://localhost:" + port + "/api/test")));
                assertNotAvailable(new URL("http://localhost:" + port + "/api/additional"));
            });
            File folder = additionalEndpointFile.getParentFile();
            folder.mkdirs();
            assertTrue(folder.exists());
            IOUtils.write(additionalEndpointClass, new FileOutputStream(additionalEndpointFile));
            retry(() -> assertEquals("available", IOUtils.toString(new URL("http://localhost:" + port + "/api/additional"))));
			retry(() -> assertEquals("simple", IOUtils.toString(new URL("http://localhost:" + port + "/api/test"))));
            quitCommand.run();
        } finally {
            additionalEndpointFile.delete();
            assertFalse(additionalEndpointFile.exists());
            mojoExecutor.join(TimeUnit.MINUTES.toMillis(1));
            if (mojoExecutor.isAlive()) {
                mojoExecutor.interrupt();
                fail("Runner didn't terminate properly");
            }
        }
    }

    private void setupWebapp(File webappDirectory) throws Exception {
        Stream.of(Endpoint.class, RsApp.class, Injectable.class, Model.class).forEach(type -> {
            final String target = type.getName().replace(".", "/");
            File targetFile = new File(webappDirectory, "WEB-INF/classes/" + target + ".class");
            FileUtils.mkDir(targetFile.getParentFile());
            try (final InputStream from = Thread.currentThread().getContextClassLoader().getResourceAsStream(target + ".class");
                 final OutputStream to = new FileOutputStream(targetFile)) {
                IO.copy(from, to);
            } catch (final IOException e) {
                fail(e.getMessage());
            }
        });
        IOUtils.write(additionalEndpointClass, new FileOutputStream(new File(webappDirectory, "WEB-INF/classes/org/app/AdditionalEndpoint.class")));
    }

    private Runnable quitCommand() {
        final InputStream in = System.in;
        final CountDownLatch latch = new CountDownLatch(1);
        System.setIn(new InputStream() {
            private final InputStream delegate = new ByteArrayInputStream("quit".getBytes(StandardCharsets.UTF_8));

            @Override
            public int read() throws IOException {
                try {
                    latch.await();
                } catch (final InterruptedException e) {
                    Thread.currentThread().interrupt();
                    fail(e.getMessage());
                }
                if (delegate.available() > 0) {
                	return delegate.read();
                } else {
                	System.setIn(in);
                	return -1;
                }
            }
        });
    	return latch::countDown;
    }

    private Thread mojoExecutor() {
        return new Thread() {
            @Override
            public void run() {
                try {
                    mojo.executeMojo(session, project, execution);
                } catch (final Exception e) {
                    fail(e.getMessage());
                }
            }
        };
    }

    private void assertNotAvailable(final URL url) {
        try {
            URLConnection connection = url.openConnection();
            connection.setReadTimeout(500);
            connection.getInputStream();
            fail(url.toString() + " is available");
        } catch (Exception e) {
            assertTrue(e.getMessage(), e instanceof IOException);
        }
    }

    private void retry(RetryTemplate retryTemplate) throws InterruptedException {
        Throwable error = null;
        for (int i = 0; i < RETRY_COUNT; i++) {
            try {
                retryTemplate.retry();
                return;
            } catch (Exception | AssertionError e) {
                error = e;
                Thread.sleep(RETRY_WAIT_PERIOD);
            }
        }
        fail(ofNullable(error).map(Throwable::getMessage).orElse("retry failes"));
    }

    interface RetryTemplate {
    	void retry() throws Exception;
    }
}
