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

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;

import freemarker.core.Environment;
import freemarker.core.Expression;
import freemarker.core.InvalidReferenceException;
import freemarker.core.ParseException;
import freemarker.core.TemplateElement;
import freemarker.core.TemplateObject;
import freemarker.core.UnboundTemplate;
import freemarker.core._CoreAPI;
import freemarker.core._ErrorDescriptionBuilder;
import freemarker.template.utility.CollectionUtils;

/**
 * Runtime exception in a template (as opposed to a parsing-time exception: {@link ParseException}).
 * It prints a special stack trace that contains the template-language stack trace along the usual Java stack trace.
 */
public class TemplateException extends Exception {

    private static final String FTL_INSTRUCTION_STACK_TRACE_TITLE
            = "FTL stack trace (\"~\" means nesting-related):";

    // Set in constructor:
    private transient _ErrorDescriptionBuilder descriptionBuilder;
    private final transient Environment env;
    private final transient Expression blamedExpression;
    private transient TemplateElement[] ftlInstructionStackSnapshot;
    
    // Calculated on demand:
    private String renderedFtlInstructionStackSnapshot;  // clalc. from ftlInstructionStackSnapshot 
    private String renderedFtlInstructionStackSnapshotTop; // clalc. from ftlInstructionStackSnapshot
    private String description;  // calc. from descriptionBuilder, or set by the construcor
    private transient String messageWithoutStackTop;
    private transient String message;
    private boolean blamedExpressionStringCalculated;
    private String blamedExpressionString;
    private boolean positionsCalculated;
    private String templateName;
    private String templateSourceName;
    private Integer lineNumber; 
    private Integer columnNumber; 
    private Integer endLineNumber; 
    private Integer endColumnNumber; 

    // Concurrency:
    private transient Object lock = new Object();
    private transient ThreadLocal messageWasAlreadyPrintedForThisTrace;
    
    /**
     * Constructs a TemplateException with no specified detail message
     * or underlying cause.
     */
    public TemplateException(Environment env) {
        this((String) null, null, env);
    }

    /**
     * Constructs a TemplateException with the given detail message,
     * but no underlying cause exception.
     *
     * @param description the description of the error that occurred
     */
    public TemplateException(String description, Environment env) {
        this(description, null, env);
    }

    /**
     * The same as {@link #TemplateException(Throwable, Environment)}; it's exists only for binary
     * backward-compatibility.
     */
    public TemplateException(Exception cause, Environment env) {
        this((String) null, cause, env);
    }

    /**
     * Constructs a TemplateException with the given underlying Exception,
     * but no detail message.
     *
     * @param cause the underlying {@link Exception} that caused this
     * exception to be raised
     * 
     * @since 2.3.20
     */
    public TemplateException(Throwable cause, Environment env) {
        this((String) null, cause, env);
    }
    
    /**
     * The same as {@link #TemplateException(String, Throwable, Environment)}; it's exists only for binary
     * backward-compatibility.
     */
    public TemplateException(String description, Exception cause, Environment env) {
        this(description, cause, env, null, null);
    }

    /**
     * Constructs a TemplateException with both a description of the error
     * that occurred and the underlying Exception that caused this exception
     * to be raised.
     *
     * @param description the description of the error that occurred
     * @param cause the underlying {@link Exception} that caused this exception to be raised
     * 
     * @since 2.3.20
     */
    public TemplateException(String description, Throwable cause, Environment env) {
        this(description, cause, env, null, null);
    }
    
    /**
     * Don't use this; this is to be used internally by FreeMarker. No backward compatibility guarantees.
     * 
     * @param blamedExpr Maybe {@code null}. The FTL stack in the {@link Environment} only specifies the error location
     *          with "template element" granularity, and this can be used to point to the expression inside the
     *          template element.    
     */
    protected TemplateException(Throwable cause, Environment env, Expression blamedExpr,
            _ErrorDescriptionBuilder descriptionBuilder) {
        this(null, cause, env, blamedExpr, descriptionBuilder);
    }
    
    private TemplateException(
            String renderedDescription,
            Throwable cause,            
            Environment env, Expression blamedExpression,
            _ErrorDescriptionBuilder descriptionBuilder) {
        // Note: Keep this constructor lightweight.
        
        super(cause);  // Message managed locally.
        
        if (env == null) env = Environment.getCurrentEnvironment();
        this.env = env;
        
        this.blamedExpression = blamedExpression;
        
        this.descriptionBuilder = descriptionBuilder;
        description = renderedDescription;
        
        if (env != null) ftlInstructionStackSnapshot = _CoreAPI.getInstructionStackSnapshot(env);
    }
    
    private void renderMessages() {
        String description = getDescription();
        
        if (description != null && description.length() != 0) {
            messageWithoutStackTop = description;
        } else if (getCause() != null) {
            messageWithoutStackTop = "No error description was specified for this error; low-level message: "
                    + getCause().getClass().getName() + ": " + getCause().getMessage();
        } else {
            messageWithoutStackTop = "[No error description was available.]";
        }
        
        String stackTopFew = getFTLInstructionStackTopFew();
        if (stackTopFew != null) {
            message = messageWithoutStackTop + "\n\n"
                    + _CoreAPI.ERROR_MESSAGE_HR + "\n"
                    + FTL_INSTRUCTION_STACK_TRACE_TITLE + "\n"
                    + stackTopFew
                    + _CoreAPI.ERROR_MESSAGE_HR;
            messageWithoutStackTop = message.substring(0, messageWithoutStackTop.length());  // to reuse backing char[]
        } else {
            message = messageWithoutStackTop;
        }
    }
    
    private void calculatePosition() {
        synchronized (lock) {
            if (!positionsCalculated) {
                // The expressions is the argument of the template element, so we prefer it as it's more specific. 
                TemplateObject templateObject = blamedExpression != null
                        ? (TemplateObject) blamedExpression
                        : (
                                ftlInstructionStackSnapshot != null && ftlInstructionStackSnapshot.length != 0
                                ? ftlInstructionStackSnapshot[0] : null);
                // Line number below 0 means no info, negative means position in ?eval-ed value that we won't use here.
                if (templateObject != null && templateObject.getBeginLine() > 0) {
                    final UnboundTemplate unboundTemplate = templateObject.getUnboundTemplate();
                    templateName = getTemplateNameOrNull(unboundTemplate);
                    templateSourceName = unboundTemplate != null ? unboundTemplate.getSourceName() : null;
                    lineNumber = Integer.valueOf(templateObject.getBeginLine());
                    columnNumber = Integer.valueOf(templateObject.getBeginColumn());
                    endLineNumber = Integer.valueOf(templateObject.getEndLine());
                    endColumnNumber = Integer.valueOf(templateObject.getEndColumn());
                }
                positionsCalculated = true;
                deleteFTLInstructionStackSnapshotIfNotNeeded();
            }
        }
    }

    private String getTemplateNameOrNull(final UnboundTemplate unboundTemplate) {
        if (unboundTemplate == null) {
            return null;
        }
        
        Template template = env != null ? env.getCurrentTemplate() : null;
        if (template == null) {
            return null;
        }
        
        return template.getUnboundTemplate() == unboundTemplate ? template.getName() : null;
    }
    
    /**
     * @deprecated Java 1.4 has introduced {@link #getCause()} - use that instead, especially as this can't return
     * runtime exceptions and errors as is.
     */
    @Deprecated
    public Exception getCauseException() {
        return getCause() instanceof Exception
                ? (Exception) getCause()
                : new Exception("Wrapped to Exception: " + getCause(), getCause());
    }

    /**
     * Returns the snapshot of the FTL stack trace at the time this exception was created.
     */
    public String getFTLInstructionStack() {
        synchronized (lock) {
            if (ftlInstructionStackSnapshot != null || renderedFtlInstructionStackSnapshot != null) {
                if (renderedFtlInstructionStackSnapshot == null) {
                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new PrintWriter(sw);
                    _CoreAPI.outputInstructionStack(ftlInstructionStackSnapshot, false, pw);
                    pw.close();
                    if (renderedFtlInstructionStackSnapshot == null) {
                        renderedFtlInstructionStackSnapshot = sw.toString();
                        deleteFTLInstructionStackSnapshotIfNotNeeded();
                    }
                }
                return renderedFtlInstructionStackSnapshot;
            } else {
                return null;
            }
        }
    }
    
    private String getFTLInstructionStackTopFew() {
        synchronized (lock) {
            if (ftlInstructionStackSnapshot != null || renderedFtlInstructionStackSnapshotTop != null) {
                if (renderedFtlInstructionStackSnapshotTop == null) {
                    int stackSize = ftlInstructionStackSnapshot.length;
                    String s;
                    if (stackSize == 0) {
                        s = "";
                    } else {
                        StringWriter sw = new StringWriter();
                        _CoreAPI.outputInstructionStack(ftlInstructionStackSnapshot, true, sw);
                        s = sw.toString();
                    }
                    if (renderedFtlInstructionStackSnapshotTop == null) {
                        renderedFtlInstructionStackSnapshotTop = s;
                        deleteFTLInstructionStackSnapshotIfNotNeeded();
                    }
                }
                return renderedFtlInstructionStackSnapshotTop.length() != 0
                        ? renderedFtlInstructionStackSnapshotTop : null;
            } else {
                return null;
            }
        }
    }
    
    private void deleteFTLInstructionStackSnapshotIfNotNeeded() {
        if (renderedFtlInstructionStackSnapshot != null && renderedFtlInstructionStackSnapshotTop != null
                && (positionsCalculated || blamedExpression != null)) {
            ftlInstructionStackSnapshot = null;
        }
        
    }
    
    private String getDescription() {
        synchronized (lock) {
            if (description == null && descriptionBuilder != null) {
                description = descriptionBuilder.toString(
                        getFailingInstruction(),
                        env != null ? env.getShowErrorTips() : true);
                descriptionBuilder = null;
            }
            return description;
        }
    }

    private TemplateElement getFailingInstruction() {
        if (ftlInstructionStackSnapshot != null && ftlInstructionStackSnapshot.length > 0) {
            return ftlInstructionStackSnapshot[0];
        } else {
            return null;
        }
    }

    /**
     * @return the execution environment in which the exception occurred.
     *    {@code null} if the exception was deserialized. 
     */
    public Environment getEnvironment() {
        return env;
    }

    /**
     * Overrides {@link Throwable#printStackTrace(PrintStream)} so that it will include the FTL stack trace.
     */
    @Override
    public void printStackTrace(PrintStream out) {
        printStackTrace(out, true, true, true);
    }

    /**
     * Overrides {@link Throwable#printStackTrace(PrintWriter)} so that it will include the FTL stack trace.
     */
    @Override
    public void printStackTrace(PrintWriter out) {
        printStackTrace(out, true, true, true);
    }
    
    /**
     * @param heading should the heading at the top be printed 
     * @param ftlStackTrace should the FTL stack trace be printed 
     * @param javaStackTrace should the Java stack trace be printed
     *  
     * @since 2.3.20
     */
    public void printStackTrace(PrintWriter out, boolean heading, boolean ftlStackTrace, boolean javaStackTrace) {
        synchronized (out) {
            printStackTrace(new PrintWriterStackTraceWriter(out), heading, ftlStackTrace, javaStackTrace);
        }
    }

    /**
     * @param heading should the heading at the top be printed 
     * @param ftlStackTrace should the FTL stack trace be printed 
     * @param javaStackTrace should the Java stack trace be printed
     *  
     * @since 2.3.20
     */
    public void printStackTrace(PrintStream out, boolean heading, boolean ftlStackTrace, boolean javaStackTrace) {
        synchronized (out) {
            printStackTrace(new PrintStreamStackTraceWriter(out), heading, ftlStackTrace, javaStackTrace);
        }
    }
    
    private void printStackTrace(StackTraceWriter out, boolean heading, boolean ftlStackTrace, boolean javaStackTrace) {
        synchronized (out) {
            if (heading) { 
                out.println("FreeMarker template error:");
            }
            
            if (ftlStackTrace) {
                String stackTrace = getFTLInstructionStack();
                if (stackTrace != null) {
                    out.println(getMessageWithoutStackTop());  // Not getMessage()!
                    out.println();
                    out.println(_CoreAPI.ERROR_MESSAGE_HR);
                    out.println(FTL_INSTRUCTION_STACK_TRACE_TITLE);
                    out.print(stackTrace);
                    out.println(_CoreAPI.ERROR_MESSAGE_HR);
                } else {
                    ftlStackTrace = false;
                    javaStackTrace = true;
                }
            }
            
            if (javaStackTrace) {
                if (ftlStackTrace) {  // We are after an FTL stack trace
                    out.println();
                    out.println("Java stack trace (for programmers):");
                    out.println(_CoreAPI.ERROR_MESSAGE_HR);
                    synchronized (lock) {
                        if (messageWasAlreadyPrintedForThisTrace == null) {
                            messageWasAlreadyPrintedForThisTrace = new ThreadLocal();
                        }
                        messageWasAlreadyPrintedForThisTrace.set(Boolean.TRUE);
                    }
                    
                    try {
                        out.printStandardStackTrace(this);
                    } finally {
                        messageWasAlreadyPrintedForThisTrace.set(Boolean.FALSE);
                    }
                } else {  // javaStackTrace only
                    out.printStandardStackTrace(this);
                }
                
                if (getCause() != null) {
                    // Dirty hack to fight with ServletException class whose getCause() method doesn't work properly:
                    Throwable causeCause = getCause().getCause();
                    if (causeCause == null) {
                        try {
                            // Reflection is used to prevent dependency on Servlet classes.
                            Method m = getCause().getClass().getMethod("getRootCause", CollectionUtils.EMPTY_CLASS_ARRAY);
                            Throwable rootCause = (Throwable) m.invoke(getCause(), CollectionUtils.EMPTY_OBJECT_ARRAY);
                            if (rootCause != null) {
                                out.println("ServletException root cause: ");
                                out.printStandardStackTrace(rootCause);
                            }
                        } catch (Throwable exc) {
                            ; // ignore
                        }
                    }
                }
            }  // if (javaStackTrace)
        }
    }
    
    /**
     * Prints the stack trace as if wasn't overridden by {@link TemplateException}. 
     * @since 2.3.20
     */
    public void printStandardStackTrace(PrintStream ps) {
        super.printStackTrace(ps);
    }

    /**
     * Prints the stack trace as if wasn't overridden by {@link TemplateException}. 
     * @since 2.3.20
     */
    public void printStandardStackTrace(PrintWriter pw) {
        super.printStackTrace(pw);
    }

    @Override
    public String getMessage() {
        if (messageWasAlreadyPrintedForThisTrace != null
                && messageWasAlreadyPrintedForThisTrace.get() == Boolean.TRUE) {
            return "[... Exception message was already printed; see it above ...]";
        } else {
            synchronized (lock) {
                if (message == null) renderMessages();
                return message;
            }
        }
    }
    
    /**
     * Similar to {@link #getMessage()}, but it doesn't contain the position of the failing instruction at then end
     * of the text. It might contains the position of the failing <em>expression</em> though as part of the expression
     * quotation, as that's the part of the description. 
     */
    public String getMessageWithoutStackTop() {
        synchronized (lock) {
            if (messageWithoutStackTop == null) renderMessages();
            return messageWithoutStackTop;
        }
    }
    
    /**
     * 1-based line number of the failing section, or {@code null} if the information is not available.
     * 
     * @since 2.3.21
     */
    public Integer getLineNumber() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return lineNumber;
        }
    }

    /**
     * Returns the name ({@link Template#getName()}) of the template where the error has occurred, or {@code null} if
     * the information isn't available. This shouldn't be used for showing the error position; use
     * {@link #getTemplateSourceName()} instead.
     * 
     * @deprecated Use {@link #getTemplateSourceName()} instead, unless you are really sure that this is what you want.
     *             This method isn't really deprecated, it's just marked so to warn users about this.
     * 
     * @since 2.3.21
     */
    @Deprecated
    public String getTemplateName() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return templateName;
        }
    }

    /**
     * Returns the source name ({@link Template#getSourceName()}) of the template where the error has occurred, or
     * {@code null} if the information isn't available. This is what should be used for showing the error position.
     * 
     * @since 2.3.22
     */
    public String getTemplateSourceName() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return templateSourceName;
        }
    }
    
    /**
     * 1-based column number of the failing section, or {@code null} if the information is not available.
     * 
     * @since 2.3.21
     */
    public Integer getColumnNumber() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return columnNumber;
        }
    }

    /**
     * 1-based line number of the last line that contains the failing section, or {@code null} if the information is not
     * available.
     * 
     * @since 2.3.21
     */
    public Integer getEndLineNumber() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return endLineNumber;
        }
    }

    /**
     * 1-based column number of the last character of the failing template section, or {@code null} if the information
     * is not available. Note that unlike with Java string API-s, this column number is inclusive.
     * 
     * @since 2.3.21
     */
    public Integer getEndColumnNumber() {
        synchronized (lock) {
            if (!positionsCalculated) {
                calculatePosition();
            }
            return endColumnNumber;
        }
    }
    
    /**
     * If there was a blamed expression attached to this exception, it returns its canonical form, otherwise it returns
     * {@code null}. This expression should always be inside the failing FTL instruction.
     *  
     * <p>The typical application of this is getting the undefined expression from {@link InvalidReferenceException}-s.
     * 
     * @since 2.3.21
     */
    public String getBlamedExpressionString() {
        synchronized (lock) {
            if (!blamedExpressionStringCalculated) {
                if (blamedExpression != null) {
                    blamedExpressionString = blamedExpression.getCanonicalForm();
                }
                blamedExpressionStringCalculated = true;
            }
            return blamedExpressionString;
        }
    }
    
    Expression getBlamedExpression() {
        return blamedExpression;
    }

    private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
        // These are calculated from transient fields, so this is the last chance to calculate them: 
        getFTLInstructionStack();
        getFTLInstructionStackTopFew();
        getDescription();
        calculatePosition();
        getBlamedExpressionString();
        
        out.defaultWriteObject();
    }
    
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        lock = new Object();
        in.defaultReadObject();
    }
    
    /** Delegate to a {@link PrintWriter} or to a {@link PrintStream}. */
    private interface StackTraceWriter {
        void print(Object obj);
        void println(Object obj);
        void println();
        void printStandardStackTrace(Throwable exception);
    }
    
    private static class PrintStreamStackTraceWriter implements StackTraceWriter {
        
        private final PrintStream out;

        PrintStreamStackTraceWriter(PrintStream out) {
            this.out = out;
        }

        public void print(Object obj) {
            out.print(obj);
        }

        public void println(Object obj) {
            out.println(obj);
        }

        public void println() {
            out.println();
        }

        public void printStandardStackTrace(Throwable exception) {
            if (exception instanceof TemplateException) {
                ((TemplateException) exception).printStandardStackTrace(out);
            } else {
                exception.printStackTrace(out);
            }
        }
        
    }

    private static class PrintWriterStackTraceWriter implements StackTraceWriter {
        
        private final PrintWriter out;

        PrintWriterStackTraceWriter(PrintWriter out) {
            this.out = out;
        }

        public void print(Object obj) {
            out.print(obj);
        }

        public void println(Object obj) {
            out.println(obj);
        }

        public void println() {
            out.println();
        }

        public void printStandardStackTrace(Throwable exception) {
            if (exception instanceof TemplateException) {
                ((TemplateException) exception).printStandardStackTrace(out);
            } else {
                exception.printStackTrace(out);
            }
        }
        
    }
    
}
