/*
 * 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.Reader;
import java.util.LinkedHashMap;
import java.util.Map;

import freemarker.cache.TemplateCache;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;
import freemarker.template.utility.NullArgumentException;

/**
 * Used for customizing the configuration settings for individual {@link Template}-s (or rather groups of templates),
 * relatively to the common setting values coming from the {@link Configuration}. This was designed with the standard
 * template loading mechanism of FreeMarker in mind ({@link Configuration#getTemplate(String)} and {@link TemplateCache}
 * ), though can also be reused for custom template loading and caching solutions.
 * 
 * <p>
 * Note on the {@code locale} setting: When used with the standard template loading/caching mechanism (
 * {@link Configuration#getTemplate(String)} and its overloads), localized lookup happens before the {@code locale}
 * specified here could have effect. The {@code locale} will be only set in the template that the localized looks has
 * already found.
 * 
 * <p>
 * Note on encoding setting {@code encoding}: See {@link #setEncoding(String)}.
 * 
 * <p>
 * Note that the result value of the reader methods (getter and "is" methods) is usually not useful unless the value of
 * that setting was already set on this object. Otherwise you will get the value from the parent {@link Configuration},
 * which is {@link Configuration#getDefaultConfiguration()} before this object is associated to a {@link Configuration}.
 * 
 * <p>
 * If you are using this class for your own template loading and caching solution, rather than with the standard one,
 * you should be aware of a few more details:
 * 
 * <ul>
 * <li>This class implements both {@link Configurable} and {@link ParserConfiguration}. This means that it can influence
 * both the template parsing phase and the runtime settings. For both aspects (i.e., {@link ParserConfiguration} and
 * {@link Configurable}) to take effect, you have first pass this object to the {@link Template} constructor
 * (this is where the {@link ParserConfiguration} interface is used), and then you have to call {@link #apply(Template)}
 * on the resulting {@link Template} object (this is where the {@link Configurable} aspect is used).
 * 
 * <li>{@link #apply(Template)} only change the settings that weren't yet set on the {@link Template} (but are inherited
 * from the {@link Configuration}). This is primarily because if the template configures itself via the {@code #ftl}
 * header, those values should have precedence. A consequence of this is that if you want to configure the same
 * {@link Template} with multiple {@link TemplateConfiguration}-s, you either should merge them to a single one before
 * that (with {@link #merge(TemplateConfiguration)}), or you have to apply them in reverse order of their intended
 * precedence.
 * </ul>
 * 
 * @see Template#Template(String, String, Reader, Configuration, ParserConfiguration, String)
 * 
 * @since 2.3.24
 */
public final class TemplateConfiguration extends Configurable implements ParserConfiguration {

    private boolean parentConfigurationSet;
    private Integer tagSyntax;
    private Integer namingConvention;
    private Boolean whitespaceStripping;
    private Boolean strictSyntaxMode;
    private Integer autoEscapingPolicy;
    private Boolean recognizeStandardFileExtensions;
    private OutputFormat outputFormat;
    private String encoding;

    /**
     * Creates a new instance. The parent will be {@link Configuration#getDefaultConfiguration()} initially, but it will
     * be changed to the real parent {@link Configuration} when this object is added to the {@link Configuration}. (It's
     * not allowed to add the same instance to multiple {@link Configuration}-s).
     */
    public TemplateConfiguration() {
        super(Configuration.getDefaultConfiguration());
    }

    /**
     * Same as {@link #setParentConfiguration(Configuration)}.
     */
    @Override
    void setParent(Configurable cfg) {
        NullArgumentException.check("cfg", cfg);
        if (!(cfg instanceof Configuration)) {
            throw new IllegalArgumentException("The parent of a TemplateConfiguration can only be a Configuration");
        }
        
        if (parentConfigurationSet) {
            if (getParent() != cfg) {
                throw new IllegalStateException(
                        "This TemplateConfiguration is already associated with a different Configuration instance.");
            }
            return;
        }
        
        if (((Configuration) cfg).getIncompatibleImprovements().intValue() < _TemplateAPI.VERSION_INT_2_3_22
                && hasAnyConfigurableSet()) {
            throw new IllegalStateException(
                    "This TemplateConfiguration can't be associated to a Configuration that has "
                    + "incompatibleImprovements less than 2.3.22, because it changes non-parser settings.");
        }
        
        super.setParent(cfg);
        parentConfigurationSet = true;
    }

    /**
     * Associates this instance with a {@link Configuration}; usually you don't call this, as it's called internally
     * when this instance is added to a {@link Configuration}. This method can be called only once (except with the same
     * {@link Configuration} parameter again, as that changes nothing anyway).
     * 
     * @throws IllegalArgumentException
     *             if the argument is {@code null} or not a {@link Configuration}
     * @throws IllegalStateException
     *             if this object is already associated to a different {@link Configuration} object,
     *             or if the {@code Configuration} has {@code #getIncompatibleImprovements()} less than 2.3.22 and
     *             this object tries to change any non-parser settings  
     */
    public void setParentConfiguration(Configuration cfg) {
        setParent(cfg);
    }

    /**
     * Returns the parent {@link Configuration}, or {@code null} if none was associated yet.
     */
    public Configuration getParentConfiguration() {
        return parentConfigurationSet ? (Configuration) getParent() : null;
    }
    
    /**
     * Set all settings in this {@link TemplateConfiguration} that were set in the parameter
     * {@link TemplateConfiguration}, possibly overwriting the earlier value in this object. (A setting is said to be
     * set in a {@link TemplateConfiguration} if it was explicitly set via a setter method, as opposed to be inherited.)
     */
    public void merge(TemplateConfiguration tc) {
        if (tc.isAPIBuiltinEnabledSet()) {
            setAPIBuiltinEnabled(tc.isAPIBuiltinEnabled());
        }
        if (tc.isArithmeticEngineSet()) {
            setArithmeticEngine(tc.getArithmeticEngine());
        }
        if (tc.isAutoEscapingPolicySet()) {
            setAutoEscapingPolicy(tc.getAutoEscapingPolicy());
        }
        if (tc.isAutoFlushSet()) {
            setAutoFlush(tc.getAutoFlush());
        }
        if (tc.isBooleanFormatSet()) {
            setBooleanFormat(tc.getBooleanFormat());
        }
        if (tc.isClassicCompatibleSet()) {
            setClassicCompatibleAsInt(tc.getClassicCompatibleAsInt());
        }
        if (tc.isCustomDateFormatsSet()) {
            setCustomDateFormats(mergeMaps(getCustomDateFormats(), tc.getCustomDateFormats()));
        }
        if (tc.isCustomNumberFormatsSet()) {
            setCustomNumberFormats(mergeMaps(getCustomNumberFormats(), tc.getCustomNumberFormats()));
        }
        if (tc.isDateFormatSet()) {
            setDateFormat(tc.getDateFormat());
        }
        if (tc.isDateTimeFormatSet()) {
            setDateTimeFormat(tc.getDateTimeFormat());
        }
        if (tc.isEncodingSet()) {
            setEncoding(tc.getEncoding());
        }
        if (tc.isLocaleSet()) {
            setLocale(tc.getLocale());
        }
        if (tc.isLogTemplateExceptionsSet()) {
            setLogTemplateExceptions(tc.getLogTemplateExceptions());
        }
        if (tc.isNamingConventionSet()) {
            setNamingConvention(tc.getNamingConvention());
        }
        if (tc.isNewBuiltinClassResolverSet()) {
            setNewBuiltinClassResolver(tc.getNewBuiltinClassResolver());
        }
        if (tc.isNumberFormatSet()) {
            setNumberFormat(tc.getNumberFormat());
        }
        if (tc.isObjectWrapperSet()) {
            setObjectWrapper(tc.getObjectWrapper());
        }
        if (tc.isOutputEncodingSet()) {
            setOutputEncoding(tc.getOutputEncoding());
        }
        if (tc.isOutputFormatSet()) {
            setOutputFormat(tc.getOutputFormat());
        }
        if (tc.isRecognizeStandardFileExtensionsSet()) {
            setRecognizeStandardFileExtensions(tc.getRecognizeStandardFileExtensions());
        }
        if (tc.isShowErrorTipsSet()) {
            setShowErrorTips(tc.getShowErrorTips());
        }
        if (tc.isSQLDateAndTimeTimeZoneSet()) {
            setSQLDateAndTimeTimeZone(tc.getSQLDateAndTimeTimeZone());
        }
        if (tc.isStrictSyntaxModeSet()) {
            setStrictSyntaxMode(tc.getStrictSyntaxMode());
        }
        if (tc.isTagSyntaxSet()) {
            setTagSyntax(tc.getTagSyntax());
        }
        if (tc.isTemplateExceptionHandlerSet()) {
            setTemplateExceptionHandler(tc.getTemplateExceptionHandler());
        }
        if (tc.isTimeFormatSet()) {
            setTimeFormat(tc.getTimeFormat());
        }
        if (tc.isTimeZoneSet()) {
            setTimeZone(tc.getTimeZone());
        }
        if (tc.isURLEscapingCharsetSet()) {
            setURLEscapingCharset(tc.getURLEscapingCharset());
        }
        if (tc.isWhitespaceStrippingSet()) {
            setWhitespaceStripping(tc.getWhitespaceStripping());
        }
        
        tc.copyDirectCustomAttributes(this, true);
    }

    /**
     * Sets the settings of the {@link Template} which are not yet set in the {@link Template} and are set in this
     * {@link TemplateConfiguration}, leaves the other settings as is. A setting is said to be set in a
     * {@link TemplateConfiguration} or {@link Template} if it was explicitly set via a setter method on that object, as
     * opposed to be inherited from the {@link Configuration}.
     * 
     * <p>
     * Note that the {@code encoding} setting of the {@link Template} counts as unset if it's {@code null},
     * even if {@code null} was set via {@link Template#setEncoding(String)}.
     *
     * @throws IllegalStateException
     *             If the parent configuration wasn't yet set.
     */
    public void apply(Template template) {
        checkParentConfigurationSet();
        Configuration cfg = getParentConfiguration();
        if (template.getConfiguration() != cfg) {
            // This is actually not a problem right now, but for future BC we enforce this.
            throw new IllegalArgumentException(
                    "The argument Template doesn't belong to the same Configuration as the TemplateConfiguration");
        }

        if (isAPIBuiltinEnabledSet() && !template.isAPIBuiltinEnabledSet()) {
            template.setAPIBuiltinEnabled(isAPIBuiltinEnabled());
        }
        if (isArithmeticEngineSet() && !template.isArithmeticEngineSet()) {
            template.setArithmeticEngine(getArithmeticEngine());
        }
        if (isAutoFlushSet() && !template.isAutoFlushSet()) {
            template.setAutoFlush(getAutoFlush());
        }
        if (isBooleanFormatSet() && !template.isBooleanFormatSet()) {
            template.setBooleanFormat(getBooleanFormat());
        }
        if (isClassicCompatibleSet() && !template.isClassicCompatibleSet()) {
            template.setClassicCompatibleAsInt(getClassicCompatibleAsInt());
        }
        if (isCustomDateFormatsSet() && !template.isCustomDateFormatsSet()) {
            template.setCustomDateFormats(getCustomDateFormats());
        }
        if (isCustomNumberFormatsSet() && !template.isCustomNumberFormatsSet()) {
            template.setCustomNumberFormats(getCustomNumberFormats());
        }
        if (isDateFormatSet() && !template.isDateFormatSet()) {
            template.setDateFormat(getDateFormat());
        }
        if (isDateTimeFormatSet() && !template.isDateTimeFormatSet()) {
            template.setDateTimeFormat(getDateTimeFormat());
        }
        if (isEncodingSet() && template.getEncoding() == null) {
            template.setEncoding(getEncoding());
        }
        if (isLocaleSet() && !template.isLocaleSet()) {
            template.setLocale(getLocale());
        }
        if (isLogTemplateExceptionsSet() && !template.isLogTemplateExceptionsSet()) {
            template.setLogTemplateExceptions(getLogTemplateExceptions());
        }
        if (isNewBuiltinClassResolverSet() && !template.isNewBuiltinClassResolverSet()) {
            template.setNewBuiltinClassResolver(getNewBuiltinClassResolver());
        }
        if (isNumberFormatSet() && !template.isNumberFormatSet()) {
            template.setNumberFormat(getNumberFormat());
        }
        if (isObjectWrapperSet() && !template.isObjectWrapperSet()) {
            template.setObjectWrapper(getObjectWrapper());
        }
        if (isOutputEncodingSet() && !template.isOutputEncodingSet()) {
            template.setOutputEncoding(getOutputEncoding());
        }
        if (isShowErrorTipsSet() && !template.isShowErrorTipsSet()) {
            template.setShowErrorTips(getShowErrorTips());
        }
        if (isSQLDateAndTimeTimeZoneSet() && !template.isSQLDateAndTimeTimeZoneSet()) {
            template.setSQLDateAndTimeTimeZone(getSQLDateAndTimeTimeZone());
        }
        if (isTemplateExceptionHandlerSet() && !template.isTemplateExceptionHandlerSet()) {
            template.setTemplateExceptionHandler(getTemplateExceptionHandler());
        }
        if (isTimeFormatSet() && !template.isTimeFormatSet()) {
            template.setTimeFormat(getTimeFormat());
        }
        if (isTimeZoneSet() && !template.isTimeZoneSet()) {
            template.setTimeZone(getTimeZone());
        }
        if (isURLEscapingCharsetSet() && !template.isURLEscapingCharsetSet()) {
            template.setURLEscapingCharset(getURLEscapingCharset());
        }
        
        copyDirectCustomAttributes(template, false);
    }

    /**
     * See {@link Configuration#setTagSyntax(int)}.
     */
    public void setTagSyntax(int tagSyntax) {
        _TemplateAPI.valideTagSyntaxValue(tagSyntax);
        this.tagSyntax = Integer.valueOf(tagSyntax);
    }

    /**
     * The getter pair of {@link #setTagSyntax(int)}.
     */
    public int getTagSyntax() {
        return tagSyntax != null ? tagSyntax.intValue() : getParentConfiguration().getTagSyntax();
    }

    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isTagSyntaxSet() {
        return tagSyntax != null;
    }

    /**
     * See {@link Configuration#setNamingConvention(int)}.
     */
    public void setNamingConvention(int namingConvention) {
        _TemplateAPI.validateNamingConventionValue(namingConvention);
        this.namingConvention = Integer.valueOf(namingConvention);
    }

    /**
     * The getter pair of {@link #setNamingConvention(int)}.
     */
    public int getNamingConvention() {
        return namingConvention != null ? namingConvention.intValue() : getParentConfiguration().getNamingConvention();
    }

    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isNamingConventionSet() {
        return namingConvention != null;
    }

    /**
     * See {@link Configuration#setWhitespaceStripping(boolean)}.
     */
    public void setWhitespaceStripping(boolean whitespaceStripping) {
        this.whitespaceStripping = Boolean.valueOf(whitespaceStripping);
    }

    /**
     * The getter pair of {@link #getWhitespaceStripping()}.
     */
    public boolean getWhitespaceStripping() {
        return whitespaceStripping != null ? whitespaceStripping.booleanValue()
                : getParentConfiguration().getWhitespaceStripping();
    }

    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isWhitespaceStrippingSet() {
        return whitespaceStripping != null;
    }

    /**
     * Sets the output format of the template; see {@link Configuration#setAutoEscapingPolicy(int)} for more.
     */
    public void setAutoEscapingPolicy(int autoEscapingPolicy) {
        _TemplateAPI.validateAutoEscapingPolicyValue(autoEscapingPolicy);
        this.autoEscapingPolicy = Integer.valueOf(autoEscapingPolicy);
    }

    /**
     * The getter pair of {@link #setAutoEscapingPolicy(int)}.
     */
    public int getAutoEscapingPolicy() {
        return autoEscapingPolicy != null ? autoEscapingPolicy.intValue()
                : getParentConfiguration().getAutoEscapingPolicy();
    }

    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isAutoEscapingPolicySet() {
        return autoEscapingPolicy != null;
    }

    /**
     * Sets the output format of the template; see {@link Configuration#setOutputFormat(OutputFormat)} for more.
     */
    public void setOutputFormat(OutputFormat outputFormat) {
        NullArgumentException.check("outputFormat", outputFormat);
        this.outputFormat = outputFormat;
    }

    /**
     * The getter pair of {@link #setOutputFormat(OutputFormat)}.
     */
    public OutputFormat getOutputFormat() {
        return outputFormat != null ? outputFormat : getParentConfiguration().getOutputFormat();
    }

    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isOutputFormatSet() {
        return outputFormat != null;
    }
    
    /**
     * See {@link Configuration#setRecognizeStandardFileExtensions(boolean)}. 
     */
    public void setRecognizeStandardFileExtensions(boolean recognizeStandardFileExtensions) {
        this.recognizeStandardFileExtensions = Boolean.valueOf(recognizeStandardFileExtensions);
    }

    /**
     * Getter pair of {@link #setRecognizeStandardFileExtensions(boolean)}.
     */
    public boolean getRecognizeStandardFileExtensions() {
        return recognizeStandardFileExtensions != null ? recognizeStandardFileExtensions.booleanValue()
                : getParentConfiguration().getRecognizeStandardFileExtensions();
    }
    
    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isRecognizeStandardFileExtensionsSet() {
        return recognizeStandardFileExtensions != null;
    }
    
    /**
     * See {@link Configuration#setStrictSyntaxMode(boolean)}.
     */
    public void setStrictSyntaxMode(boolean strictSyntaxMode) {
        this.strictSyntaxMode = Boolean.valueOf(strictSyntaxMode);
    }

    /**
     * The getter pair of {@link #setStrictSyntaxMode(boolean)}.
     */
    public boolean getStrictSyntaxMode() {
        return strictSyntaxMode != null ? strictSyntaxMode.booleanValue()
                : getParentConfiguration().getStrictSyntaxMode();
    }
    
    /**
     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
     */
    public boolean isStrictSyntaxModeSet() {
        return strictSyntaxMode != null;
    }

    @Override
    public void setStrictBeanModels(boolean strict) {
        throw new UnsupportedOperationException(
                "Setting strictBeanModels on " + TemplateConfiguration.class.getSimpleName() + " level isn't supported.");
    }

    public String getEncoding() {
        return encoding != null ? encoding : getParentConfiguration().getDefaultEncoding();
    }

    /**
     * When the standard template loading/caching mechanism is used, this forces the charset used for reading the
     * template "file", overriding everything but the encoding coming from the {@code #ftl} header. This setting
     * overrides the locale-specific encodings set via {@link Configuration#setEncoding(java.util.Locale, String)}. It
     * also overrides the {@code encoding} parameter of {@link Configuration#getTemplate(String, String)} (and of its
     * overloads) and the {@code encoding} parameter of the {@code #include} directive. This works like that because
     * specifying the encoding where you are requesting the template is error prone and deprecated.
     * 
     * <p>
     * If you are developing your own template loading/caching mechanism instead of the standard one, note that the
     * above behavior is not guaranteed by this class alone; you have to ensure it. Also, read the note on
     * {@code encoding} in the documentation of {@link #apply(Template)}.
     */
    public void setEncoding(String encoding) {
        NullArgumentException.check("encoding", encoding);
        this.encoding = encoding;
    }

    public boolean isEncodingSet() {
        return encoding != null;
    }
    
    /**
     * Returns {@link Configuration#getIncompatibleImprovements()} from the parent {@link Configuration}. This mostly
     * just exist to satisfy the {@link ParserConfiguration} interface.
     * 
     * @throws IllegalStateException
     *             If the parent configuration wasn't yet set.
     */
    public Version getIncompatibleImprovements() {
        checkParentConfigurationSet();
        return getParentConfiguration().getIncompatibleImprovements();
    }

    private void checkParentConfigurationSet() {
        if (!parentConfigurationSet) {
            throw new IllegalStateException("The TemplateConfiguration wasn't associated with a Configuration yet.");
        }
    }

    private boolean hasAnyConfigurableSet() {
        return
                isAPIBuiltinEnabledSet()
                || isArithmeticEngineSet()
                || isAutoFlushSet()
                || isBooleanFormatSet()
                || isClassicCompatibleSet()
                || isCustomDateFormatsSet()
                || isCustomNumberFormatsSet()
                || isDateFormatSet()
                || isDateTimeFormatSet()
                || isLocaleSet()
                || isLogTemplateExceptionsSet()
                || isNewBuiltinClassResolverSet()
                || isNumberFormatSet()
                || isObjectWrapperSet()
                || isOutputEncodingSet()
                || isShowErrorTipsSet()
                || isSQLDateAndTimeTimeZoneSet()
                || isTemplateExceptionHandlerSet()
                || isTimeFormatSet()
                || isTimeZoneSet()
                || isURLEscapingCharsetSet();
    }
    
    private Map mergeMaps(Map m1, Map m2) {
        if (m1 == null) return m2;
        if (m2 == null) return m1;
        if (m1.isEmpty()) return m2;
        if (m2.isEmpty()) return m1;
        
        LinkedHashMap mergedM = new LinkedHashMap(m1);
        mergedM.putAll(m2);
        return mergedM;
    }
    
}
