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

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.utility.StringUtil;
import junit.framework.TestCase;

/**
 * Test various generated templates (permutations), including some deliberately
 * wrong ones, with various tag_syntax settings.  
 */
public class TagSyntaxVariationsTest extends TestCase {
    
    private static final String HDR_ANG = "<#ftl>";
    private static final String HDR_SQU = squarify(HDR_ANG);
    private static final String IF_ANG = "<#if true>i</#if>";
    private static final String IF_SQU = squarify(IF_ANG);
    private static final String IF_OUT = "i";
    private static final String ASSIGN_ANG = "<#assign x = 1>a";
    private static final String ASSIGN_SQU = squarify(ASSIGN_ANG);
    private static final String ASSIGN_OUT = "a";
    private static final String WRONG_ANG = "<#wrong>";
    private static final String WRONG_SQU = squarify(WRONG_ANG);
    private static final String WRONGC_ANG = "</#wrong>";
    private static final String WRONGC_SQU = squarify(WRONGC_ANG );
    private static final String CUST_ANG = "<@compress> z </@>";
    private static final String CUST_SQU = squarify(CUST_ANG);
    private static final String CUST_OUT = "z";
    
    public TagSyntaxVariationsTest(String name) {
        super(name);
    }
    
    private static String squarify(String s) {
        return s.replace('<', '[').replace('>', ']');
    }

    public final void test()
            throws TemplateException, IOException {
        Configuration cfgBuggy = new Configuration();
        // Default on 2.3.x: cfgBuggy.setEmulate23ParserBugs(true);
        // Default on 2.3.x: cfgBuggy.setTagSyntax(Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        
        Configuration cfgFixed = new Configuration();
        cfgFixed.setIncompatibleImprovements(Configuration.VERSION_2_3_19);
        // Default on 2.3.x: cfgFixed.setTagSyntax(Configuration.ANGLE_BRACKET_TAG_SYNTAX);

        // Permutations 
        for (int ifOrAssign = 0; ifOrAssign < 2; ifOrAssign++) {
            String dir_ang = ifOrAssign == 0 ? IF_ANG : ASSIGN_ANG; 
            String dir_squ = ifOrAssign == 0 ? IF_SQU : ASSIGN_SQU; 
            String dir_out = ifOrAssign == 0 ? IF_OUT : ASSIGN_OUT; 
            
            // Permutations 
            for (int angOrSqu = 0; angOrSqu < 2; angOrSqu++) {
                cfgBuggy.setTagSyntax(angOrSqu == 0
                        ? Configuration.ANGLE_BRACKET_TAG_SYNTAX
                        : Configuration.SQUARE_BRACKET_TAG_SYNTAX);
                cfgFixed.setTagSyntax(angOrSqu == 0
                        ? Configuration.ANGLE_BRACKET_TAG_SYNTAX
                        : Configuration.SQUARE_BRACKET_TAG_SYNTAX);
                
                String dir_xxx = angOrSqu == 0 ? dir_ang : dir_squ;
                String cust_xxx = angOrSqu == 0 ? CUST_ANG : CUST_SQU;
                String hdr_xxx = angOrSqu == 0 ? HDR_ANG : HDR_SQU;
                String wrong_xxx = angOrSqu == 0 ? WRONG_ANG : WRONG_SQU;
                String wrongc_xxx = angOrSqu == 0 ? WRONGC_ANG : WRONGC_SQU;
                
                test(cfgBuggy,
                        dir_xxx + cust_xxx,
                        dir_out + CUST_OUT);
                test(cfgFixed,
                        dir_xxx + cust_xxx,
                        dir_out + CUST_OUT);
                
                // Permutations 
                for (int wrongOrWrongc = 0; wrongOrWrongc < 2; wrongOrWrongc++) {
                    String wrongx_xxx = wrongOrWrongc == 0 ? wrong_xxx : wrongc_xxx;
                    
                    // Bug: initial unknown # tags are treated as static text
                    test(cfgBuggy,
                            wrongx_xxx + dir_xxx,
                            wrongx_xxx + dir_out);
                    test(cfgFixed,
                            wrongx_xxx + dir_xxx,
                            null);
    
                    // Bug: same as above
                    test(cfgBuggy,
                            wrongx_xxx + wrongx_xxx + dir_xxx,
                            wrongx_xxx + wrongx_xxx + dir_out);
                    
                    test(cfgBuggy,
                            dir_xxx + wrongx_xxx,
                            null);
                    test(cfgFixed,
                            dir_xxx + wrongx_xxx,
                            null);
                    
                    test(cfgBuggy,
                            hdr_xxx + wrongx_xxx,
                            null);
                    test(cfgFixed,
                            hdr_xxx + wrongx_xxx,
                            null);
                    
                    test(cfgBuggy,
                            cust_xxx + wrongx_xxx + dir_xxx,
                            null);
                    test(cfgFixed,
                            cust_xxx + wrongx_xxx + dir_xxx,
                            null);
                } // for wrongc
            } // for squ
            
            cfgBuggy.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
            cfgFixed.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
            for (int perm = 0; perm < 4; perm++) {
                // All 4 permutations
                String wrong_xxx = (perm & 1) == 0 ? WRONG_ANG : WRONG_SQU;
                String dir_xxx = (perm & 2) == 0 ? dir_ang : dir_squ;
                
                // Bug: Auto-detection ignores unknown # tags
                test(cfgBuggy,
                        wrong_xxx + dir_xxx,
                        wrong_xxx + dir_out);
                test(cfgFixed,
                        wrong_xxx + dir_xxx,
                        null);
                
                // Bug: same as above
                test(cfgBuggy,
                        wrong_xxx + wrong_xxx + dir_xxx,
                        wrong_xxx + wrong_xxx + dir_out);
            } // for perm
    
            // Permutations 
            for (int angOrSquStart = 0; angOrSquStart < 2; angOrSquStart++) {
                String hdr_xxx = angOrSquStart == 0 ? HDR_ANG : HDR_SQU;
                String cust_xxx = angOrSquStart == 0 ? CUST_ANG : CUST_SQU;
                String wrong_yyy = angOrSquStart != 0 ? WRONG_ANG : WRONG_SQU;
                String dir_xxx = angOrSquStart == 0 ? dir_ang : dir_squ;
                String dir_yyy = angOrSquStart != 0 ? dir_ang : dir_squ;
                
                test(cfgBuggy,
                        cust_xxx + wrong_yyy + dir_xxx,
                        CUST_OUT + wrong_yyy + dir_out);
                test(cfgFixed,
                        cust_xxx + wrong_yyy + dir_xxx,
                        CUST_OUT + wrong_yyy + dir_out);
                
                test(cfgBuggy,
                        hdr_xxx + wrong_yyy + dir_xxx,
                        wrong_yyy + dir_out);
                test(cfgFixed,
                        hdr_xxx + wrong_yyy + dir_xxx,
                        wrong_yyy + dir_out);
                
                test(cfgBuggy,
                        cust_xxx + wrong_yyy + dir_yyy,
                        CUST_OUT + wrong_yyy + dir_yyy);
                test(cfgFixed,
                        cust_xxx + wrong_yyy + dir_yyy,
                        CUST_OUT + wrong_yyy + dir_yyy);
                
                test(cfgBuggy,
                        hdr_xxx + wrong_yyy + dir_yyy,
                        wrong_yyy + dir_yyy);
                test(cfgFixed,
                        hdr_xxx + wrong_yyy + dir_yyy,
                        wrong_yyy + dir_yyy);
                
                test(cfgBuggy,
                        dir_xxx + wrong_yyy + dir_yyy,
                        dir_out + wrong_yyy + dir_yyy);
                test(cfgFixed,
                        dir_xxx + wrong_yyy + dir_yyy,
                        dir_out + wrong_yyy + dir_yyy);
            } // for squStart
            
        } // for assign
    }
    
    /**
     * @param expected the expected output or <tt>null</tt> if we expect
     * a parsing error.
     */
    private static final void test(
            Configuration cfg, String template, String expected)
            throws TemplateException, IOException {
        Template t = null;
        try {
            t = new Template("string", new StringReader(template), cfg);
        } catch (ParseException e) {
            if (expected != null) {
                fail("Couldn't create Template from "
                        + StringUtil.jQuote(template) + ": " + e);
            } else {
                return;
            }
        }
        if (expected == null) fail("Template parsing should have fail for "
                + StringUtil.jQuote(template));
        
        StringWriter out = new StringWriter();
        t.process(new Object(), out);
        assertEquals(expected, out.toString());
    }

}
