/*
 * 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 freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * A class that allows one to associate custom data with a {@link Configuration}, a {@link Template}, or
 * {@link Environment}.
 * 
 * <p>This API has similar approach to that of {@link ThreadLocal} (which allows one to associate
 * custom data with a thread). With an example:</p>
 * 
 * <pre>
 * // The object identity itself will serve as the attribute identifier; there's no attribute name String:
 * public static final CustomAttribute MY_ATTR = new CustomAttribute(CustomAttribute.SCOPE_CONFIGURATION);
 * ...
 *     // Set the attribute in this particular Configuration object:
 *     MY_ATTR.set(myAttrValue, cfg);
 *     ...
 *     // Read the attribute from this particular Configuration object:
 *     myAttrValue = MY_ATTR.get(cfg);
 * </pre>
 */
public class CustomAttribute {
    
    /**
     * Constant used in the constructor specifying that this attribute is {@link Environment}-scoped.
     */
    public static final int SCOPE_ENVIRONMENT = 0;
        
    /**
     * Constant used in the constructor specifying that this attribute is {@link Template}-scoped.
     */
    public static final int SCOPE_TEMPLATE = 1;
        
    /**
     * Constant used in the constructor specifying that this attribute is {@link Configuration}-scoped.
     */
    public static final int SCOPE_CONFIGURATION = 2;

    // We use an internal key instead of 'this' so that malicious subclasses 
    // overriding equals() and hashCode() can't gain access to other attribute
    // values. That's also the reason why get() and set() are marked final.
    private final Object key = new Object();
    private final int scope;
    
    /**
     * Creates a new custom attribute with the specified scope
     * @param scope one of <tt>SCOPE_</tt> constants. 
     */
    public CustomAttribute(int scope) {
        if (scope != SCOPE_ENVIRONMENT && 
           scope != SCOPE_TEMPLATE && 
           scope != SCOPE_CONFIGURATION) {
                throw new IllegalArgumentException();
            }
        this.scope = scope;
    }
    
    /**
     * This method is invoked when {@link #get()} is invoked without 
     * {@link #set(Object)} being invoked before it to define the value in the 
     * current scope. Override it to create the attribute value on-demand.  
     * @return the initial value for the custom attribute. By default returns null.
     */
    protected Object create() {
        return null;
    }
    
    /**
     * Gets the attribute from the appropriate scope that's accessible through the specified {@link Environment}. If
     * the attribute has {@link #SCOPE_ENVIRONMENT} scope, it will be get from the given {@link Environment} directly.
     * If the attribute has {@link #SCOPE_TEMPLATE} scope, it will be get from the parent of the given
     * {@link Environment} (that is, in {@link Environment#getParent()}) directly). If the attribute has
     * {@link #SCOPE_CONFIGURATION} scope, it will be get from {@link Environment#getConfiguration()}.
     * 
     * @throws NullPointerException
     *             If {@code env} is null
     * 
     * @return The new value of the attribute (possibly {@code null}), or {@code null} if the attribute doesn't exist.
     * 
     * @since 2.3.22
     */
    public final Object get(Environment env) {
        return getScopeConfigurable(env).getCustomAttribute(key, this);
    }

    /**
     * Same as {@link #get(Environment)}, but uses {@link Environment#getCurrentEnvironment()} to fill the 2nd argument.
     * 
     * @throws IllegalStateException
     *             If there is no current {@link Environment}, which is usually the case when the current thread isn't
     *             processing a template.
     */
    public final Object get() {
        return getScopeConfigurable(getRequiredCurrentEnvironment()).getCustomAttribute(key, this);
    }
    
    /**
     * Gets the value of a {@link Template}-scope attribute from the given {@link Template}.
     * 
     * @throws UnsupportedOperationException
     *             If this custom attribute has different scope than {@link #SCOPE_TEMPLATE}.
     * @throws NullPointerException
     *             If {@code template} is null
     */
    public final Object get(Template template) {
        if (scope != SCOPE_TEMPLATE) {
            throw new UnsupportedOperationException("This is not a template-scope attribute");
        }
        return ((Configurable) template).getCustomAttribute(key, this);
    }
    
    /**
     * Same as {@link #get(Template)}, but applies to a {@link TemplateConfiguration}.  
     * 
     * @since 2.3.24
     */
    public Object get(TemplateConfiguration templateConfiguration) {
        if (scope != SCOPE_TEMPLATE) {
            throw new UnsupportedOperationException("This is not a template-scope attribute");
        }
        return templateConfiguration.getCustomAttribute(key, this);
    }
    
    /**
     * Gets the value of a {@link Configuration}-scope attribute from the given {@link Configuration}.
     * 
     * @throws UnsupportedOperationException
     *             If this custom attribute has different scope than {@link #SCOPE_CONFIGURATION}.
     * @throws NullPointerException
     *             If {@code cfg} is null
     * 
     * @since 2.3.22
     */
    public final Object get(Configuration cfg) {
        if (scope != SCOPE_CONFIGURATION) {
            throw new UnsupportedOperationException("This is not a template-scope attribute");
        }
        return ((Configurable) cfg).getCustomAttribute(key, this);
    }
    
    /**
     * Sets the attribute inside the appropriate scope that's accessible through the specified {@link Environment}. If
     * the attribute has {@link #SCOPE_ENVIRONMENT} scope, it will be set in the given {@link Environment} directly. If
     * the attribute has {@link #SCOPE_TEMPLATE} scope, it will be set in the parent of the given {@link Environment}
     * (that is, in {@link Environment#getParent()}) directly). If the attribute has {@link #SCOPE_CONFIGURATION} scope,
     * it will be set in {@link Environment#getConfiguration()}.
     * 
     * @param value
     *            The new value of the attribute. Can be {@code null}.
     * 
     * @throws NullPointerException
     *             If {@code env} is null
     * 
     * @since 2.3.22
     */
    public final void set(Object value, Environment env) {
        getScopeConfigurable(env).setCustomAttribute(key, value);
    }

    /**
     * Same as {@link #set(Object, Environment)}, but uses {@link Environment#getCurrentEnvironment()} to fill the 2nd
     * argument.
     * 
     * @throws IllegalStateException
     *             If there is no current {@link Environment}, which is usually the case when the current thread isn't
     *             processing a template.
     */
    public final void set(Object value) {
        getScopeConfigurable(getRequiredCurrentEnvironment()).setCustomAttribute(key, value);
    }

    /**
     * Sets the value of a {@link Template}-scope attribute in the given {@link Template}.
     * 
     * @param value
     *            The new value of the attribute. Can be {@code null}.
     * 
     * @throws UnsupportedOperationException
     *             If this custom attribute has different scope than {@link #SCOPE_TEMPLATE}.
     * @throws NullPointerException
     *             If {@code template} is null
     */
    public final void set(Object value, Template template) {
        if (scope != SCOPE_TEMPLATE) {
            throw new UnsupportedOperationException("This is not a template-scope attribute");
        }
        ((Configurable) template).setCustomAttribute(key, value);
    }

    /**
     * Same as {@link #set(Object, Template)}, but applicable to a {@link TemplateConfiguration}. 
     * 
     * @since 2.3.24
     */
    public final void set(Object value, TemplateConfiguration templateConfiguration) {
        if (scope != SCOPE_TEMPLATE) {
            throw new UnsupportedOperationException("This is not a template-scope attribute");
        }
        templateConfiguration.setCustomAttribute(key, value);
    }
    
    /**
     * Sets the value of a {@link Configuration}-scope attribute in the given {@link Configuration}.
     * 
     * @param value
     *            The new value of the attribute. Can be {@code null}.
     * 
     * @throws UnsupportedOperationException
     *             If this custom attribute has different scope than {@link #SCOPE_CONFIGURATION}.
     * @throws NullPointerException
     *             If {@code cfg} is null
     * 
     * @since 2.3.22
     */
    public final void set(Object value, Configuration cfg) {
        if (scope != SCOPE_CONFIGURATION) {
            throw new UnsupportedOperationException("This is not a configuration-scope attribute");
        }
        ((Configurable) cfg).setCustomAttribute(key, value);
    }
    
    private Environment getRequiredCurrentEnvironment() {
        Environment c = Environment.getCurrentEnvironment();
        if (c == null) {
            throw new IllegalStateException("No current environment");
        }
        return c;
    }

    private Configurable getScopeConfigurable(Environment env) throws Error {
        switch (scope) {
        case SCOPE_ENVIRONMENT:
            return env;
        case SCOPE_TEMPLATE:
            return env.getParent();
        case SCOPE_CONFIGURATION:
            return env.getParent().getParent();
        default:
            throw new BugException();
        }
    }
    
}
