/*
 * 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;  // calc. from ftlInstructionStackSnapshot 
    private String renderedFtlInstructionStackSnapshotTop; // calc. 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(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(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(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
                        ? 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;
        }

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

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

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

        @Override
        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;
        }

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

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

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

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