/*
 * 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.*\\.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;
        }

    }

}
