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

import static org.junit.Assert.*;

import java.io.IOException;

import org.junit.Test;

public class ActualTagSyntaxTest {

    @Test
    public void testWithFtlHeader() throws IOException {
        testWithFtlHeader(Configuration.AUTO_DETECT_TAG_SYNTAX);
        testWithFtlHeader(Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        testWithFtlHeader(Configuration.SQUARE_BRACKET_TAG_SYNTAX);
    }
    
    private void testWithFtlHeader(int cfgTagSyntax) throws IOException {
        assertEquals(getActualTagSyntax("[#ftl]foo", cfgTagSyntax), Configuration.SQUARE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("<#ftl>foo", cfgTagSyntax), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
    }
    
    @Test
    public void testUndecidable() throws IOException {
        assertEquals(getActualTagSyntax("foo", Configuration.AUTO_DETECT_TAG_SYNTAX), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo", Configuration.ANGLE_BRACKET_TAG_SYNTAX), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo", Configuration.SQUARE_BRACKET_TAG_SYNTAX), Configuration.SQUARE_BRACKET_TAG_SYNTAX);
    }

    @Test
    public void testDecidableWithoutFtlHeader() throws IOException {
        assertEquals(getActualTagSyntax("foo<#if true></#if>", Configuration.AUTO_DETECT_TAG_SYNTAX), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo<#if true></#if>", Configuration.ANGLE_BRACKET_TAG_SYNTAX), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo<#if true></#if>", Configuration.SQUARE_BRACKET_TAG_SYNTAX), Configuration.SQUARE_BRACKET_TAG_SYNTAX);
        
        assertEquals(getActualTagSyntax("foo[#if true][/#if]", Configuration.AUTO_DETECT_TAG_SYNTAX), Configuration.SQUARE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo[#if true][/#if]", Configuration.ANGLE_BRACKET_TAG_SYNTAX), Configuration.ANGLE_BRACKET_TAG_SYNTAX);
        assertEquals(getActualTagSyntax("foo[#if true][/#if]", Configuration.SQUARE_BRACKET_TAG_SYNTAX), Configuration.SQUARE_BRACKET_TAG_SYNTAX);
    }
    
    private int getActualTagSyntax(String ftl, int cfgTagSyntax) throws IOException {
        Configuration cfg = new Configuration();
        cfg.setTagSyntax(cfgTagSyntax);
        return new Template(null, ftl, cfg).getActualTagSyntax();
    }
    
}
