/*
 * 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 static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Test;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class ConfigurableTest {

    @Test
    public void testGetSettingNamesAreSorted() throws Exception {
        Configurable cfgable = createConfigurable();
        for (boolean camelCase : new boolean[] { false, true }) {
            Collection<String> names = cfgable.getSettingNames(camelCase);
            String prevName = null;
            for (String name : names) {
                if (prevName != null) {
                    assertThat(name, greaterThan(prevName));
                }
                prevName = name;
            }
        }
    }

    @Test
    public void testStaticFieldKeysCoverAllGetSettingNames() throws Exception {
        Configurable cfgable = createConfigurable();
        Collection<String> names = cfgable.getSettingNames(false);
        for (String name : names) {
                assertTrue("No field was found for " + name, keyFieldExists(name));
        }
    }
    
    @Test
    public void testGetSettingNamesCoversAllStaticKeyFields() throws Exception {
        Configurable cfgable = createConfigurable();
        Collection<String> names = cfgable.getSettingNames(false);
        
        for (Field f : Configurable.class.getFields()) {
            if (f.getName().endsWith("_KEY")) {
                final Object name = f.get(null);
                assertTrue("Missing setting name: " + name, names.contains(name));
            }
        }
    }

    @Test
    public void testKeyStaticFieldsHasAllVariationsAndCorrectFormat() throws IllegalArgumentException, IllegalAccessException {
        ConfigurableTest.testKeyStaticFieldsHasAllVariationsAndCorrectFormat(Configurable.class);
    }
    
    @Test
    public void testGetSettingNamesNameConventionsContainTheSame() throws Exception {
        Configurable cfgable = createConfigurable();
        ConfigurableTest.testGetSettingNamesNameConventionsContainTheSame(
                new ArrayList<>(cfgable.getSettingNames(false)),
                new ArrayList<>(cfgable.getSettingNames(true)));
    }

    public static void testKeyStaticFieldsHasAllVariationsAndCorrectFormat(
            Class<? extends Configurable> confClass) throws IllegalArgumentException, IllegalAccessException {
        // For all _KEY fields there must be a _KEY_CAMEL_CASE and a _KEY_SNAKE_CASE field.
        // Their content must not contradict the expected naming convention.
        // They _KEY filed value must be deducable from the field name
        // The _KEY value must be the same as _KEY_SNAKE_CASE field.
        // The _KEY_CAMEL_CASE converted to snake case must give the value of the _KEY_SNAKE_CASE.
        for (Field field : confClass.getFields()) {
            String fieldName = field.getName();
            if (fieldName.endsWith("_KEY")) {
                String keyFieldValue = (String) field.get(null);
                assertNotEquals(Configuration.CAMEL_CASE_NAMING_CONVENTION,
                        _CoreStringUtils.getIdentifierNamingConvention(keyFieldValue));
                assertEquals(fieldName.substring(0, fieldName.length() - 4).toLowerCase(), keyFieldValue);
                
                try {
                    String keySCFieldValue = (String) confClass.getField(fieldName + "_SNAKE_CASE").get(null);
                    assertEquals(keyFieldValue, keySCFieldValue);
                } catch (NoSuchFieldException e) {
                    fail("Missing ..._SNAKE_CASE field for " + fieldName);
                }
                
                try {
                    String keyCCFieldValue = (String) confClass.getField(fieldName + "_CAMEL_CASE").get(null);
                    assertNotEquals(Configuration.LEGACY_NAMING_CONVENTION,
                            _CoreStringUtils.getIdentifierNamingConvention(keyCCFieldValue));
                    assertEquals(keyFieldValue, _CoreStringUtils.camelCaseToUnderscored(keyCCFieldValue));
                } catch (NoSuchFieldException e) {
                    fail("Missing ..._CAMEL_CASE field for " + fieldName);
                }
            }
        }
        
        // For each _KEY_SNAKE_CASE field there must be a _KEY field.
        for (Field field : confClass.getFields()) {
            String fieldName = field.getName();
            if (fieldName.endsWith("_KEY_SNAKE_CASE")) {
                try {
                    confClass.getField(fieldName.substring(0, fieldName.length() - 11)).get(null);
                } catch (NoSuchFieldException e) {
                    fail("Missing ..._KEY field for " + fieldName);
                }
            }
        }
        
        // For each _KEY_CAMEL_CASE field there must be a _KEY field.
        for (Field field : confClass.getFields()) {
            String fieldName = field.getName();
            if (fieldName.endsWith("_KEY_CAMEL_CASE")) {
                try {
                    confClass.getField(fieldName.substring(0, fieldName.length() - 11)).get(null);
                } catch (NoSuchFieldException e) {
                    fail("Missing ..._KEY field for " + fieldName);
                }
            }
        }
    }
    
    public static void testGetSettingNamesNameConventionsContainTheSame(List<String> namesSCList, List<String> namesCCList) {
        Set<String> namesSC = new HashSet<>(namesSCList);
        assertEquals(namesSCList.size(), namesSC.size());
        
        Set<String> namesCC = new HashSet<>(namesCCList);
        assertEquals(namesCCList.size(), namesCC.size());

        assertEquals(namesSC.size(), namesCC.size());
        
        for (String nameCC : namesCC) {
            final String nameSC = _CoreStringUtils.camelCaseToUnderscored(nameCC);
            if (!namesSC.contains(nameSC)) {
                fail("\"" + nameCC + "\" misses corresponding snake case name, \"" + nameSC + "\".");
            }
        }
    }
    
    private Configurable createConfigurable() throws IOException {
        return new Template(null, "", new Configuration(Configuration.VERSION_2_3_22));
    }

    private boolean keyFieldExists(String name) throws Exception {
        try {
            Configurable.class.getField(name.toUpperCase() + "_KEY");
        } catch (NoSuchFieldException e) {
            return false;
        }
        return true;
    }

}
