/*
 * 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 freemarker.core.Environment.Namespace;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * A macro or function (or other future callable entity) associated to a namespace and a template.
 * 
 * <p>
 * With an analogy, a {@link UnboundCallable} is like a non-static {@link java.lang.reflect.Method} in Java; it
 * describes everything about the method, but it isn't bound to any object on which the method could be called.
 * Continuing this analogy, a {@link BoundCallable} is like a {@link java.lang.reflect.Method} paired with the object
 * whose method it is (the {@code this} object), and is thus callable in itself. In the case of FTL macros and FTL
 * functions, instead of a single {@code this} object, we have two such objects: a namespace and a template. (One may
 * wonder why the namespace is not enough, given that a namespace already specifies a template (
 * {@link Namespace#getTemplate()} ). It's because a namespace can contain macros from included templates, and so the
 * template that the callable belongs to isn't always the same as {@link Namespace#getTemplate()}, which just gives the
 * "root" template of the namespace. Furthermore, several namespaces my include exactly the same template, so we can't
 * get away with a template instead of a namespace either. Also note that knowing which template we are in is needed for
 * example to resolve relative references to other templates.)
 * 
 * <p>
 * Historical note: Prior to 2.4, the two concepts ({@link UnboundCallable} and {@link BoundCallable}) were these same,
 * represented by {@link Macro}, which still exists due to backward compatibility constraints. This class extends
 * {@link Macro} only for the sake of legacy applications which expect macro and function FTL variables to be
 * {@link Macro}-s. Especially, this class should not extend {@link TemplateElement} (which it does, because
 * {@link Macro} is a subclass of that), but it had to, for backward compatibility. It just delegates the {@link Macro}
 * methods to the embedded {@link UnboundCallable}.
 * 
 * @see UnboundCallable
 * 
 * @since 2.4.0
 */
final class BoundCallable extends Macro {
    
    private final UnboundCallable unboundCallable;
    private final Template template;
    private final Namespace namespace;
    
    BoundCallable(UnboundCallable callableDefinition, Template template, Namespace namespace) {
        this.unboundCallable = callableDefinition;
        this.template = template;
        this.namespace = namespace;
    }

    UnboundCallable getUnboundCallable() {
        return unboundCallable;
    }
    
    Template getTemplate() {
        return template;
    }
    
    Namespace getNamespace() {
        return namespace;
    }

    @Override
    public String toString() {
        return "BoundCallable("
                + "name=" + getName()
                + ", isFunction=" + isFunction()
                + ", template" + (template != null ? ".name=" + template.getName() : "=null")
                + ", namespace=" + (namespace != null ? namespace.getTemplate().getName() : "null")
                + ")";
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    public String getCatchAll() {
        return unboundCallable.getCatchAll();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    public String[] getArgumentNames() {
        return unboundCallable.getArgumentNames();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    public String getName() {
        return unboundCallable.getName();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    public boolean isFunction() {
        return unboundCallable.isFunction();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    TemplateElement[] accept(Environment env) throws TemplateException, IOException {
        return unboundCallable.accept(env);
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    protected String dump(boolean canonical) {
        return unboundCallable.dump(canonical);
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    String getNodeTypeSymbol() {
        return unboundCallable.getNodeTypeSymbol();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    int getParameterCount() {
        return unboundCallable.getParameterCount();
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    Object getParameterValue(int idx) {
        return unboundCallable.getParameterValue(idx);
    }

    /** For backward compatibility only; delegates to the {@link UnboundCallable}'s identical method. */
    @Override
    ParameterRole getParameterRole(int idx) {
        return unboundCallable.getParameterRole(idx);
    }

    @Override
    boolean isNestedBlockRepeater() {
        return unboundCallable.isNestedBlockRepeater();
    }
    
}
