/*
 * 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._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 blow 0 means no info, negative means position in ?eval-ed value that we won't use here.
                if (templateObject != null && templateObject.getBeginLine() > 0) {
                    final Template template = templateObject.getTemplate();
                    templateName = template != null ? template.getName() : null;
                    templateSourceName = template != null ? template.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();
            }
        }
    }
    
    /**
     * @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);
            }
        }
        
    }
    
}
