/*
 * 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 freemarker.test.servlet;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import freemarker.test.ResourcesExtractor;
import freemarker.test.utility.TestUtil;

public class WebAppTestCase {

    public static final String IGNORED_MASK = "[IGNORED]";

    private static final Logger LOG = LoggerFactory.getLogger(WebAppTestCase.class);

    private static final String ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN
            = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";

    private static final String EXPECTED_DIR = "WEB-INF/expected/";

    private static Server server;
    private static ContextHandlerCollection contextHandlers;
    private static Map<String, WebAppContext> deployedWebApps = new HashMap<>();
    private static volatile File testTempDirectory;

    @BeforeClass
    public static void beforeClass() throws Exception {
        // Work around Java 5 bug(?) that causes Jasper to fail with "zip file closed" when it reads the JSTL jar:
        org.eclipse.jetty.util.resource.Resource.setDefaultUseCaches(false);

        LOG.info("Starting embedded Jetty...");

        server = new Server(0);

        contextHandlers = new ContextHandlerCollection();
        server.setHandler(contextHandlers);

        server.start();
    }

    @AfterClass
    public static void afterClass() throws Exception {
        LOG.info("Stopping embedded Jetty...");
        server.stop();
        server.join();
        LOG.info("Jetty stopped.");
        deleteTemporaryDirectories();
    }

    protected final String getResponseContent(String webAppName, String webAppRelURL) throws Exception {
        HTTPResponse resp = getHTTPResponse(webAppName, webAppRelURL);
        if (resp.getStatusCode() != HttpURLConnection.HTTP_OK) {
            fail("Expected HTTP status " + HttpURLConnection.HTTP_OK + ", but got "
                    + resp.getStatusCode() + " (message: " + resp.getStatusMessage() + ") for URI "
                    + resp.getURI());
        }
        return resp.getContent();
    }

    protected final int getResponseStatusCode(String webAppName, String webAppRelURL) throws Exception {
        HTTPResponse resp = getHTTPResponse(webAppName, webAppRelURL);
        return resp.getStatusCode();
    }

    protected final HTTPResponse getHTTPResponse(String webAppName, String webAppRelURL) throws Exception {
        if (webAppName.startsWith("/") || webAppName.endsWith("/")) {
            throw new IllegalArgumentException("\"webAppName\" can't start or end with \"/\": " + webAppName);
        }
        if (webAppRelURL.startsWith("/") || webAppRelURL.endsWith("/")) {
            throw new IllegalArgumentException("\"webappRelURL\" can't start or end with \"/\": " + webAppRelURL);
        }

        ensureWebAppIsDeployed(webAppName);

        final URI uri = new URI("http://localhost:" + ((NetworkConnector) server.getConnectors()[0]).getLocalPort()
                + "/" + webAppName + "/" + webAppRelURL);

        final HttpURLConnection httpCon = (HttpURLConnection) uri.toURL().openConnection();
        httpCon.connect();
        try {
            LOG.debug("HTTP GET: {}", uri);

            final int responseCode = httpCon.getResponseCode();

            final String content;
            if (responseCode == 200) {
                try (InputStream in = httpCon.getInputStream()) {
                    content = IOUtils.toString(in, "UTF-8");
                }
            } else {
                content = null;
            }

            return new HTTPResponse(
                    responseCode, httpCon.getResponseMessage(),
                    content,
                    uri);
        } finally {
            httpCon.disconnect();
        }
    }

    /**
     * Compares the output of the JSP and the FTL version of the same page, ignoring some of the whitespace differences.
     * 
     * @param webAppRelURLWithoutExt
     *            something like {@code "tester?view=foo"}, which will be extended to {@code "tester?view=foo.jsp"} and
     *            {@code "tester?view=foo.ftl"}, and then the output of these extended URL-s will be compared.
     */
    protected void assertJSPAndFTLOutputEquals(String webAppName, String webAppRelURLWithoutExt) throws Exception {
        assertOutputsEqual(webAppName, webAppRelURLWithoutExt + ".jsp", webAppRelURLWithoutExt + ".ftl");
    }

    protected void assertOutputsEqual(String webAppName, String webAppRelURL1, final String webAppRelURL2)
            throws Exception {
        String jspOutput = normalizeWS(getResponseContent(webAppName, webAppRelURL1), true);
        String ftlOutput = normalizeWS(getResponseContent(webAppName, webAppRelURL2), true);
        assertEquals(jspOutput, ftlOutput);
    }

    protected void assertExpectedEqualsOutput(String webAppName, String expectedFileName, String webAppRelURL)
            throws Exception {
        assertExpectedEqualsOutput(webAppName, expectedFileName, webAppRelURL, true);
    }

    protected void assertExpectedEqualsOutput(String webAppName, String expectedFileName, String webAppRelURL,
            boolean compressWS) throws Exception {
        assertExpectedEqualsOutput(webAppName, expectedFileName, webAppRelURL, compressWS, null);
    }

    /**
     * @param expectedFileName
     *            The name of the file that stores the expected content, relatively to
     *            {@code servketContext:/WEB-INF/expected}.
     * @param ignoredParts
     *            Parts that will be search-and-replaced with {@value #IGNORED_MASK} with both in the expected and
     *            actual outputs.
     */
    protected void assertExpectedEqualsOutput(String webAppName, String expectedFileName, String webAppRelURL,
            boolean compressWS, List<Pattern> ignoredParts) throws Exception {
        final String actual = normalizeWS(getResponseContent(webAppName, webAppRelURL), compressWS);
        final String expected;
        {
            ClassPathResource cpResource = findWebAppDirectoryResource(webAppName);
            try (InputStream in = cpResource.resolverClass.getResourceAsStream(
                    cpResource.path + EXPECTED_DIR + expectedFileName)) {
                expected = TestUtil.removeTxtCopyrightComment(normalizeWS(IOUtils.toString(in, "utf-8"), compressWS));
            }
        }
        assertEquals(maskIgnored(expected, ignoredParts), maskIgnored(actual, ignoredParts));
    }

    private String maskIgnored(String s, List<Pattern> ignoredParts) {
        if (ignoredParts == null) return s;

        for (Pattern ignoredPart : ignoredParts) {
            s = ignoredPart.matcher(s).replaceAll(IGNORED_MASK);
        }
        return s;
    }

    protected synchronized void restartWebAppIfStarted(String webAppName) throws Exception {
        WebAppContext context = deployedWebApps.get(webAppName);
        if (context != null) {
            context.stop();
            context.start();
        }
    }

    private Pattern BR = Pattern.compile("\r\n|\r");
    private Pattern MULTI_LINE_WS = Pattern.compile("[\t ]*[\r\n][\t \r\n]*", Pattern.DOTALL);
    private Pattern SAME_LINE_WS = Pattern.compile("[\t ]+", Pattern.DOTALL);

    private String normalizeWS(String s, boolean compressWS) {
        if (compressWS) {
            return SAME_LINE_WS.matcher(
                    MULTI_LINE_WS.matcher(s).replaceAll("\n"))
                    .replaceAll(" ")
                    .trim();
        } else {
            return BR.matcher(s).replaceAll("\n");
        }
    }

    private synchronized void ensureWebAppIsDeployed(String webAppName) throws Exception {
        if (deployedWebApps.containsKey(webAppName)) {
            return;
        }

        final String webAppDirURL = createWebAppDirAndGetURI(webAppName);

        WebAppContext context = new WebAppContext(webAppDirURL, "/" + webAppName);

        // Pattern of jar file names scanned for META-INF/*.tld:
        context.setAttribute(
                ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN,
                ".*(taglib|jsp\\.jstl).*\\.jar$");

        addJasperInitializer(context);

        contextHandlers.addHandler(context);
        // As we add this after the Server was started, it has to be started manually:
        context.start();

        deployedWebApps.put(webAppName, context);
        LOG.info("Deployed web app.: {}", webAppName);
    }

    /**
     * Without this, we will have this error when loading a taglib:
     * NullPointerException: Cannot invoke "org.apache.jasper.compiler.TldCache.getTldResourcePath(String)" because the
     * return value of "org.apache.jasper.Options.getTldCache()" is null
     */
    private static void addJasperInitializer(WebAppContext context) {
        JettyJasperInitializer jettyJasperInitializer = new JettyJasperInitializer();
        ServletContainerInitializersStarter servletContainerInitializersStarter
                = new ServletContainerInitializersStarter(context);
        ContainerInitializer containerInitializer = new ContainerInitializer(jettyJasperInitializer, null);
        context.setAttribute("org.eclipse.jetty.containerInitializers", List.of(containerInitializer));
        context.addBean(servletContainerInitializersStarter, true);
    }

    private static void deleteTemporaryDirectories() throws IOException {
        if (testTempDirectory.getParentFile() == null) {
            throw new IOException("Won't delete the root directory");
        }
        try {
            FileUtils.forceDelete(testTempDirectory);
        } catch (IOException e) {
            LOG.warn("Failed to delete temporary file or directory; will re-try on JVM shutdown: "
                    + testTempDirectory);
            FileUtils.forceDeleteOnExit(testTempDirectory);
        }
    }

    @SuppressFBWarnings(value = "UI_INHERITANCE_UNSAFE_GETRESOURCE", justification = "By design relative to subclass")
    private String createWebAppDirAndGetURI(String webAppName) throws IOException {
        ClassPathResource resourceDir = findWebAppDirectoryResource(webAppName);
        File temporaryDir = ResourcesExtractor.extract(
                resourceDir.resolverClass, resourceDir.path, new File(getTestTempDirectory(), webAppName));
        return temporaryDir.toURI().toString();
    }

    private ClassPathResource findWebAppDirectoryResource(String webAppName) throws IOException {
        final String appRelResPath = "webapps/" + webAppName + "/";
        final String relResPath = appRelResPath + "WEB-INF/web.xml";

        Class<?> baseClass = this.getClass();
        do {
            URL r = baseClass.getResource(relResPath);
            if (r != null) {
                return new ClassPathResource(baseClass, appRelResPath);
            }

            baseClass = baseClass.getSuperclass();
            if (!WebAppTestCase.class.isAssignableFrom(baseClass)) {
                throw new IOException("Can't find test class relative resource: " + relResPath);
            }
        } while (true);
    }
    
    private File getTestTempDirectory() throws IOException {
        if (testTempDirectory == null) {
            // As at least on Windows we have problem deleting the directories once Jetty has used them (the file
            // handles of the jars remain open), we always use the same name, so that at most one will remain there.
            File d = new File(
                    new File(System.getProperty("java.io.tmpdir")),
                    "freemarker-jetty-junit-tests-(delete-it)");
            if (d.exists()) {
                FileUtils.deleteDirectory(d);
            }
            if (!d.mkdirs()) {
               throw new IOException("Failed to create Jetty temp directory: " + d); 
            }
            testTempDirectory = d;
        }
        return testTempDirectory;
    }

    private static class ClassPathResource {

        private final Class<?> resolverClass;
        private final String path;

        public ClassPathResource(Class<?> resolverClass, String path) {
            this.resolverClass = resolverClass;
            this.path = path;
        }

    }

    private static class HTTPResponse {

        private final int statusCode;
        private final String content;
        private final String statusMessage;
        private final URI uri;

        public HTTPResponse(int statusCode, String statusMessage, String content, URI uri) {
            this.statusCode = statusCode;
            this.content = content;
            this.statusMessage = statusMessage;
            this.uri = uri;
        }

        public String getStatusMessage() {
            return statusMessage;
        }

        public int getStatusCode() {
            return statusCode;
        }

        public String getContent() {
            return content;
        }

        public URI getURI() {
            return uri;
        }

    }

}
