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

/**
 * <b>Internal API - subject to change:</b> Represent a node in the parsed template (either a {@link Expression} or a
 * {@link TemplateElement}).
 * 
 * @see TemplateElement
 * @see Expression
 * 
 * @deprecated This is an internal FreeMarker API with no backward compatibility guarantees, so you shouldn't depend on
 *             it.
 */
@Deprecated
public abstract class TemplateObject {
    
    private UnboundTemplate unboundTemplate;
    int beginColumn, beginLine, endColumn, endLine;
    
    /** This is needed for an ?eval hack; the expression AST nodes will be the descendants of the template, however,
     *  we can't give their position in the template, only in the dynamic string that's evaluated. That's signaled
     *  by a negative line numbers, starting from this constant as line 1. */
    static final int RUNTIME_EVAL_LINE_DISPLACEMENT = -1000000000;  

    final void setLocation(UnboundTemplate unboundTemplate, Token begin, Token end) {
        setLocation(unboundTemplate, begin.beginColumn, begin.beginLine, end.endColumn, end.endLine);
    }

    final void setLocation(UnboundTemplate unboundTemplate, Token tagBegin, Token tagEnd, TemplateElements children) {
        TemplateElement lastChild = children.getLast();
        if (lastChild != null) {
            // [<#if exp>children]<#else>
            setLocation(unboundTemplate, tagBegin, lastChild);
        } else {
            // [<#if exp>]<#else>
            setLocation(unboundTemplate, tagBegin, tagEnd);
        }
    }
    
    final void setLocation(UnboundTemplate unboundTemplate, Token begin, TemplateObject end) {
        setLocation(unboundTemplate, begin.beginColumn, begin.beginLine, end.endColumn, end.endLine);
    }
    
    final void setLocation(UnboundTemplate unboundTemplate, TemplateObject begin, Token end) {
        setLocation(unboundTemplate, begin.beginColumn, begin.beginLine, end.endColumn, end.endLine);
    }

    final void setLocation(UnboundTemplate unboundTemplate, TemplateObject begin, TemplateObject end) {
        setLocation(unboundTemplate, begin.beginColumn, begin.beginLine, end.endColumn, end.endLine);
    }

    void setLocation(UnboundTemplate unboundTemplate, int beginColumn, int beginLine, int endColumn, int endLine) {
        this.unboundTemplate = unboundTemplate;
        this.beginColumn = beginColumn;
        this.beginLine = beginLine;
        this.endColumn = endColumn;
        this.endLine = endLine;
    }
    
    /**
     * <b>Internal API - subject to change</b>
     */
    public final int getBeginColumn() {
        return beginColumn;
    }

    /**
     * <b>Internal API - subject to change</b>
     */
    public final int getBeginLine() {
        return beginLine;
    }

    /**
     * <b>Internal API - subject to change</b>
     */
    public final int getEndColumn() {
        return endColumn;
    }

    /**
     * <b>Internal API - subject to change</b>
     */
    public final int getEndLine() {
        return endLine;
    }

    /**
     * <b>Internal API - subject to change</b>;
     * Returns a string that indicates
     * where in the template source, this object is.
     */
    public String getStartLocation() {
        return MessageUtil.formatLocationForEvaluationError(unboundTemplate, beginLine, beginColumn);
    }

    /**
     * <b>Internal API - subject to change</b>
     * 
     * <p>As of 2.3.20. the same as {@link #getStartLocation}. Meant to be used where there's a risk of XSS
     * when viewing error messages.
     */
    public String getStartLocationQuoted() {
        return getStartLocation();
    }

    /**
     * <b>Internal API - subject to change</b>
     */
    public String getEndLocation() {
        return MessageUtil.formatLocationForEvaluationError(unboundTemplate, endLine, endColumn);
    }

    /**
     * <b>Internal API - subject to change</b>
     * 
     * <p>As of 2.3.20. the same as {@link #getEndLocation}. Meant to be used where there's a risk of XSS
     * when viewing error messages.
     */
    public String getEndLocationQuoted() {
        return getEndLocation();
    }
    
    /**
     * <b>Internal API - subject to change</b>
     */
    public final String getSource() {
        String s;
        if (unboundTemplate != null) {
            s = unboundTemplate.getSource(beginColumn, beginLine, endColumn, endLine);
        } else {
            s = null;
        }

        // Can't just return null for backward-compatibility... 
        return s != null ? s : getCanonicalForm();
    }

    @Override
    public String toString() {
        String s;
    	try {
    		s = getSource();
    	} catch (Exception e) { // REVISIT: A bit of a hack? (JR)
    	    s = null;
    	}
    	return s != null ? s : getCanonicalForm();
    }

    /**
     * <b>Internal API - subject to change</b>
     * 
     * @return whether the point in the template file specified by the column and line numbers is contained within this
     *         template object.
     */
    public boolean contains(int column, int line) {
        if (line < beginLine || line > endLine) {
            return false;
        }
        if (line == beginLine) {
            if (column < beginColumn) {
                return false;
            }
        }
        if (line == endLine) {
            if (column > endColumn) {
                return false;
            }
        }
        return true;
    }

    /**
     * <b>Internal API - subject to change</b>
     * 
     * @since 2.4.0
     */
    public UnboundTemplate getUnboundTemplate() {
        return unboundTemplate;
    }

    TemplateObject copyLocationFrom(TemplateObject from) {
        unboundTemplate = from.unboundTemplate;
        beginColumn = from.beginColumn;
        beginLine = from.beginLine;
        endColumn = from.endColumn;
        endLine = from.endLine;
        return this;
    }    

    /**
     * <b>Internal API - subject to change</b>; FTL generated from the AST of the node, which must be parseable to an
     * AST that does the same as the original source, assuming we turn off automatic white-space removal when parsing
     * the canonical form.
     * 
     * @see TemplateElement#getDescription()
     * @see #getNodeTypeSymbol()
     */
    abstract public String getCanonicalForm();
    
    /**
     * A very sort single-line string that describes what kind of AST node this is, without describing any 
     * embedded expression or child element. Examples: {@code "#if"}, {@code "+"}, <tt>"${...}</tt>. These values should
     * be suitable as tree node labels in a tree view. Yet, they should be consistent and complete enough so that an AST
     * that is equivalent with the original could be reconstructed from the tree view. Thus, for literal values that are
     * leaf nodes the symbols should be the canonical form of value.
     * 
     * Note that {@link TemplateElement#getDescription()} has similar role, only it doesn't go under the element level
     * (i.e. down to the expression level), instead it always prints the embedded expressions itself.
     * 
     * @see #getCanonicalForm()
     * @see TemplateElement#getDescription()
     */
    abstract String getNodeTypeSymbol();
    
    /**
     * Returns highest valid parameter index + 1. So one should scan indexes with {@link #getParameterValue(int)}
     * starting from 0 up until but excluding this. For example, for the binary "+" operator this will give 2, so the
     * legal indexes are 0 and 1. Note that if a parameter is optional in a template-object-type and happens to be
     * omitted in an instance, this will still return the same value and the value of that parameter will be
     * {@code null}.
     */
    abstract int getParameterCount();
    
    /**
     * Returns the value of the parameter identified by the index. For example, the binary "+" operator will have an
     * LHO {@link Expression} at index 0, and and RHO {@link Expression} at index 1. Or, the binary "." operator will
     * have an LHO {@link Expression} at index 0, and an RHO {@link String}(!) at index 1. Or, the {@code #include}
     * directive will have a path {@link Expression} at index 0, a "parse" {@link Expression} at index 1, etc.
     * 
     * <p>The index value doesn't correspond to the source-code location in general. It's an arbitrary identifier
     * that corresponds to the role of the parameter instead. This also means that when a parameter is omitted, the
     * index of the other parameters won't shift.
     *
     *  @return {@code null} or any kind of {@link Object}, very often an {@link Expression}. However, if there's
     *      a {@link TemplateObject} stored inside the returned value, it must itself be be a {@link TemplateObject}
     *      too, otherwise the AST couldn't be (easily) fully traversed. That is, non-{@link TemplateObject} values
     *      can only be used for leafs. 
     *  
     *  @throws IndexOutOfBoundsException if {@code idx} is less than 0 or not less than {@link #getParameterCount()}. 
     */
    abstract Object getParameterValue(int idx);

    /**
     *  Returns the role of the parameter at the given index, like {@link ParameterRole#LEFT_HAND_OPERAND}.
     *  
     *  As of this writing (2013-06-17), for directive parameters it will always give {@link ParameterRole#UNKNOWN},
     *  because there was no need to be more specific so far. This should be improved as need.
     *  
     *  @throws IndexOutOfBoundsException if {@code idx} is less than 0 or not less than {@link #getParameterCount()}. 
     */
    abstract ParameterRole getParameterRole(int idx);
    
}
