/*
 * 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.ext.jsp;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Ignore;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.BeansWrapperBuilder;
import freemarker.ext.servlet.FreemarkerServlet;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.ObjectWrapper;
import freemarker.template.SimpleObjectWrapper;
import freemarker.template.TemplateExceptionHandler;
import freemarker.test.servlet.DefaultModel2TesterAction;
import freemarker.test.servlet.WebAppTestCase;

/**
 * Tests {@link FreemarkerServlet} on a real (embedded) Servlet container.
 */
@SuppressWarnings("boxing")
@SuppressFBWarnings(value="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification="Hack needed for testing only")
public class RealServletContainertTest extends WebAppTestCase {

    private static final String WEBAPP_BASIC = "basic";
    private static final String WEBAPP_TLD_DISCOVERY = "tldDiscovery";
    private static final String WEBAPP_ERRORS = "errors";
    private static final String WEBAPP_CONFIG = "config";
    private static final String WEBAPP_MULTIPLE_LOADERS = "multipleLoaders";

    @Test
    public void basicTrivial() throws Exception {
        assertJSPAndFTLOutputEquals(WEBAPP_BASIC, "tester?view=trivial");
    }

    @Test
    @Ignore  // c:forEach fails because of EL context issues
    public void basicTrivialJSTL() throws Exception {
        assertOutputsEqual(WEBAPP_BASIC, "tester?view=trivial.jsp", "tester?view=trivial-jstl-@Ignore.ftl");        
    }

    @Test
    public void basicCustomTags1() throws Exception {
        assertExpectedEqualsOutput(WEBAPP_BASIC, "customTags1.txt", "tester?view=customTags1.ftl", false);
    }

    @Test
    public void basicCustomAttributes() throws Exception {
        restartWebAppIfStarted(WEBAPP_BASIC);  // To clear the application scope attributes
        assertExpectedEqualsOutput(WEBAPP_BASIC, "attributes.txt", "tester"
                + "?action=" + AllKindOfContainersModel2Action.class.getName()
                + "&view=attributes.ftl");

        restartWebAppIfStarted(WEBAPP_BASIC);  // To clear the application scope attributes
        assertExpectedEqualsOutput(WEBAPP_BASIC, "attributes-2.3.22-future.txt", "tester"
                + "?action=" + AllKindOfContainersModel2Action.class.getName()
                + "&view=attributes.ftl&viewServlet=freemarker-2.3.22-future");
        
        restartWebAppIfStarted(WEBAPP_BASIC);  // To clear the application scope attributes
        assertExpectedEqualsOutput(WEBAPP_BASIC, "attributes-2.3.0.txt", "tester"
                + "?action=" + AllKindOfContainersModel2Action.class.getName()
                + "&view=attributes.ftl&viewServlet=freemarker-2.3.0",
                true,
                ImmutableList.of(
                        Pattern.compile("(?<=^Date-time: ).*", Pattern.MULTILINE), // Uses Date.toString, so plat. dep.
                        Pattern.compile("(?<=^MyMap: ).*", Pattern.MULTILINE)  // Uses HashMap, so order unknown
                        ));
    }

    @Test
    public void basicELFunctions() throws Exception {
        assertJSPAndFTLOutputEquals(WEBAPP_BASIC, "tester?view=customELFunctions1");
    }

    // https://issues.apache.org/jira/browse/FREEMARKER-18
    @Test
    public void basicELFunctionsTagNameClash() throws Exception {
        // System.out.println(getResponseContent(WEBAPP_BASIC, "tester?view=elFunctionsTagNameClash.jsp"));
        // System.out.println(getResponseContent(WEBAPP_BASIC, "tester?view=elFunctionsTagNameClash.ftl"));
        assertJSPAndFTLOutputEquals(WEBAPP_BASIC, "tester?view=elFunctionsTagNameClash");
    }
    
    @Test
    public void tldDiscoveryBasic() throws Exception {
        try {
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "test1.txt", "tester?view=test1.ftl");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
        }
    }

    @Test
    public void tldDiscoveryBasicDefultOverride() throws Exception {
        try {
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "test1.txt",
                    "tester?view=test1.ftl&viewServlet=freemarker-defaultOverride");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
        }
    }
    
    @Test
    public void tldDiscoveryEmulatedProblems1() throws Exception {
        try {
            JspTestFreemarkerServlet.emulateNoJarURLConnections = true;
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "test1.txt", "tester?view=test1.ftl");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
        }       
    }

    @Test
    public void tldDiscoveryEmulatedProblems2() throws Exception {
        try {
            JspTestFreemarkerServlet.emulateNoJarURLConnections = true;
            JspTestFreemarkerServlet.emulateNoUrlToFileConversions = true;
            // Because of emulateNoUrlToFileConversions = true it won't be able to list the directories, so:
            System.setProperty(
                    FreemarkerServlet.SYSTEM_PROPERTY_CLASSPATH_TLDS,
                    "META-INF/tldDiscovery MetaInfTldSources-1.tld");
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "test1.txt", "tester?view=test1.ftl");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
            System.clearProperty(FreemarkerServlet.SYSTEM_PROPERTY_CLASSPATH_TLDS);
        }
    }

    @Test
    public void tldDiscoveryClasspathOnly() throws Exception {
        try {
            System.setProperty(FreemarkerServlet.SYSTEM_PROPERTY_META_INF_TLD_SOURCES, "clear, classpath");
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "test1.txt", "tester?view=test1.ftl");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
            System.clearProperty(FreemarkerServlet.SYSTEM_PROPERTY_META_INF_TLD_SOURCES);
        }
    }

    /**
     * Tests that (1) webInfPerLibJars still loads from WEB-INF/lib/*.jar, and (2) that
     * {@link FreemarkerServlet#SYSTEM_PROPERTY_META_INF_TLD_SOURCES} indeed overrides the init-param, and that the
     * Jetty container's JSTL jar-s will still be discovered.
     */
    @Test
    public void tldDiscoveryNoClasspath() throws Exception {
        try {
            System.setProperty(FreemarkerServlet.SYSTEM_PROPERTY_META_INF_TLD_SOURCES, "clear, webInfPerLibJars");
            restartWebAppIfStarted(WEBAPP_TLD_DISCOVERY);
            assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY,
                    "test-noClasspath.txt", "tester?view=test-noClasspath.ftl");
        } finally {
            JspTestFreemarkerServlet.resetToDefaults();
            System.clearProperty(FreemarkerServlet.SYSTEM_PROPERTY_META_INF_TLD_SOURCES);
        }
    }
    
    @Test
    public void tldDiscoveryRelative() throws Exception {
        assertExpectedEqualsOutput(WEBAPP_TLD_DISCOVERY, "subdir/test-rel.txt", "tester?view=subdir/test-rel.ftl");
    }

    @Test
    public void errorStatusCodes() throws Exception {
        assertEquals(404, getResponseStatusCode(WEBAPP_ERRORS, "missing.jsp"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS, "failing-runtime.jsp"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS, "failing-parsetime.jsp"));

        assertEquals(200, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=not-failing.ftl&viewServlet=freemarker-default-dev"));
        assertEquals(404, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=missing.ftl&viewServlet=freemarker-default-dev"));
        assertEquals(200, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-runtime.ftl&viewServlet=freemarker-default-dev"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-parsetime.ftlnv&viewServlet=freemarker-default-dev"));
        
        assertEquals(200, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=not-failing.ftl&viewServlet=freemarker-default-prod"));
        assertEquals(404, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=missing.ftl&viewServlet=freemarker-default-prod"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-runtime.ftl&viewServlet=freemarker-default-prod"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-parsetime.ftlnv&viewServlet=freemarker-default-prod"));
        
        assertEquals(200, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=not-failing.ftl&viewServlet=freemarker-future-prod"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=missing.ftl&viewServlet=freemarker-future-prod"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-runtime.ftl&viewServlet=freemarker-future-prod"));
        assertEquals(500, getResponseStatusCode(WEBAPP_ERRORS,
                "tester?view=failing-parsetime.ftlnv&viewServlet=freemarker-future-prod"));
    }
    
    @Test
    public void testTemplateLoaderConfig() throws Exception {
        assertEquals("from /WEB-INF/classes", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-class-root"));
        assertEquals("from WEB-INF/lib/templates.jar/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=sub/test2.ftl&viewServlet=freemarker-class-root"));
        assertEquals("from /WEB-INF/classes/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-class-sub"));
        assertEquals("from WEB-INF/lib/templates.jar/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test2.ftl&viewServlet=freemarker-class-sub"));
        
        assertEquals("from /WEB-INF/classes", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-classpath-root"));
        assertEquals("from WEB-INF/lib/templates.jar/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=sub/test2.ftl&viewServlet=freemarker-classpath-root"));
        assertEquals("from /WEB-INF/classes/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-classpath-sub"));
        assertEquals("from WEB-INF/lib/templates.jar/sub", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test2.ftl&viewServlet=freemarker-classpath-sub"));
        
        assertEquals("from /WEB-INF/templates", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-webinfPerTemplates"));
        assertEquals("from /", getResponseContent(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-contentRoot"));
    }
    
    @Test
    public void testConfigurationDefaults() throws Exception {
        assertEquals(200, getResponseStatusCode(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-assertDefaultsFreemarkerServlet"));
        assertEquals(200, getResponseStatusCode(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-assertDefaultsIcI2322FreemarkerServlet"));
        assertEquals(200, getResponseStatusCode(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-assertCustomizedDefaultsFreemarkerServlet"));
        assertEquals(200, getResponseStatusCode(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-assertObjectWrapperDefaults1FreemarkerServlet"));
        assertEquals(200, getResponseStatusCode(WEBAPP_CONFIG,
                "tester?view=test.ftl&viewServlet=freemarker-assertObjectWrapperDefaults2FreemarkerServlet"));
    }
    
    @Test
    public void testMultipleLoaders() throws Exception {
       assertEquals("In test.ftl",
               getResponseContent(WEBAPP_MULTIPLE_LOADERS, "tester?view=test.ftl")); 
       assertEquals("In classpath-test.ftl",
               getResponseContent(WEBAPP_MULTIPLE_LOADERS, "tester?view=classpath-test.ftl")); 
    }

    public static class AllKindOfContainersModel2Action extends DefaultModel2TesterAction {

        @Override
        public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            req.setAttribute("linkedList", initTestCollection(new LinkedList<Integer>()));
            req.setAttribute("arrayList", initTestCollection(new ArrayList<Integer>()));
            req.setAttribute("myList", new MyList());
            
            req.setAttribute("linkedHashMap", initTestMap(new LinkedHashMap()));
            req.setAttribute("treeMap", initTestMap(new TreeMap()));
            req.setAttribute("myMap", new MyMap());
            
            req.setAttribute("treeSet", initTestCollection(new TreeSet()));
            
            return super.execute(req, resp);
        }
        
        private Collection<Integer> initTestCollection(Collection<Integer> list) {
            for (int i = 0; i < 3; i++) list.add(i + 1);
            return list;
        }

        private Map<String, Integer> initTestMap(Map<String, Integer> map) {
            for (int i = 0; i < 3; i++) map.put(String.valueOf((char) ('a' + i)), i + 1);
            return map;
        }
        
    }
    
    public static class MyMap extends AbstractMap<String, Integer> {

        @Override
        public Set<Map.Entry<String, Integer>> entrySet() {
            return ImmutableSet.<Map.Entry<String, Integer>>of(
                    new MyEntry("a", 1), new MyEntry("b", 2), new MyEntry("c", 3));
        }
        
        private static class MyEntry implements Map.Entry<String, Integer> {
            
            private final String key;
            private final Integer value;

            public MyEntry(String key, Integer value) {
                this.key = key;
                this.value = value;
            }

            public String getKey() {
                return key;
            }

            public Integer getValue() {
                return value;
            }

            public Integer setValue(Integer value) {
                throw new UnsupportedOperationException();
            }
            
        }
        
    }
    
    public static class MyList extends AbstractList<Integer> {

        @SuppressWarnings("boxing")
        @Override
        public Integer get(int index) {
            return index + 1;
        }

        @Override
        public int size() {
            return 3;
        }
        
    }
    
    public static abstract class AssertingFreemarkerServlet extends FreemarkerServlet {

        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                IOException {
            Configuration cfg = getConfiguration();
            try {
                doAssertions(cfg);
            } catch (Exception e) {
                throw new ServletException("Test failed", e);
            }
            
            response.setStatus(200);
            response.getWriter().write("OK");
        }

        protected abstract void doAssertions(Configuration cfg) throws Exception;
        
    }
    
    public static class AssertDefaultsFreemarkerServlet extends AssertingFreemarkerServlet {

        @Override
        protected void doAssertions(Configuration cfg) {
            assertEquals(Configuration.VERSION_2_3_22, cfg.getIncompatibleImprovements());
            
            assertSame(cfg.getTemplateExceptionHandler(), TemplateExceptionHandler.HTML_DEBUG_HANDLER);
            
            assertFalse(cfg.getLogTemplateExceptions());
            
            {
                ObjectWrapper ow = cfg.getObjectWrapper();
                assertTrue(ow instanceof DefaultObjectWrapper);
                assertEquals(Configuration.VERSION_2_3_22, ((DefaultObjectWrapper) ow).getIncompatibleImprovements());
            }
            
            {
                TemplateLoader tl = cfg.getTemplateLoader();
                assertTrue(tl instanceof ClassTemplateLoader);
                assertEquals("/", ((ClassTemplateLoader) tl).getBasePackagePath());
            }
            
        }
        
    }

    public static class AssertDefaultsIcI2322FreemarkerServlet extends AssertDefaultsFreemarkerServlet {

        @Override
        protected Configuration createConfiguration() {
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
            return cfg;
        }
        
    }
    
    public static class AssertCustomizedDefaultsFreemarkerServlet extends AssertingFreemarkerServlet {

        @Override
        protected Configuration createConfiguration() {
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_20);
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            cfg.setLogTemplateExceptions(true);
            cfg.setObjectWrapper(new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build());
            cfg.setTemplateLoader(new WebappTemplateLoader(getServletContext()));
            return cfg;
        }

        @Override
        protected void doAssertions(Configuration cfg) {
            assertEquals(Configuration.VERSION_2_3_20, cfg.getIncompatibleImprovements());
            
            assertSame(cfg.getTemplateExceptionHandler(), TemplateExceptionHandler.RETHROW_HANDLER);
            
            assertTrue(cfg.getLogTemplateExceptions());
            
            {
                ObjectWrapper ow = cfg.getObjectWrapper();
                assertSame(BeansWrapper.class, ow.getClass());
                assertEquals(Configuration.VERSION_2_3_21, ((BeansWrapper) ow).getIncompatibleImprovements());
            }
            
            {
                TemplateLoader tl = cfg.getTemplateLoader();
                assertTrue(tl instanceof WebappTemplateLoader);
            }
            
        }
        
    }
    
    public static class AssertObjectWrapperDefaults1FreemarkerServlet extends AssertingFreemarkerServlet {

        @Override
        protected void doAssertions(Configuration cfg) throws Exception {
            ObjectWrapper ow = cfg.getObjectWrapper();
            assertSame(BeansWrapper.class, ow.getClass());
            assertEquals(Configuration.VERSION_2_3_21, ((BeansWrapper) ow).getIncompatibleImprovements());
        }

        @Override
        protected ObjectWrapper createDefaultObjectWrapper() {
            return new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
        }
        
    }

    public static class AssertObjectWrapperDefaults2FreemarkerServlet extends
            AssertObjectWrapperDefaults1FreemarkerServlet {

        @Override
        protected Configuration createConfiguration() {
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_20);
            cfg.setObjectWrapper(new SimpleObjectWrapper(Configuration.VERSION_2_3_22));
            return cfg;
        }
        
        @Override
        protected void doAssertions(Configuration cfg) throws Exception {
            ObjectWrapper ow = cfg.getObjectWrapper();
            assertSame(SimpleObjectWrapper.class, ow.getClass());
            assertEquals(Configuration.VERSION_2_3_22, ((BeansWrapper) ow).getIncompatibleImprovements());
        }
        
    }
    
}
