/*
 * 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 org.apache.commons.lang.exception;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * <p>A shared implementation of the nestable exception functionality.</p>
 * <p>
 * The code is shared between 
 * {@link org.apache.commons.lang.exception.NestableError NestableError},
 * {@link org.apache.commons.lang.exception.NestableException NestableException} and
 * {@link org.apache.commons.lang.exception.NestableRuntimeException NestableRuntimeException}.
 * </p>
 * 
 * @author Apache Software Foundation
 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
 * @author Daniel L. Rall
 * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
 * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
 * @author Sean C. Sullivan
 * @since 1.0
 * @version $Id$
 */
public class NestableDelegate implements Serializable {

    /**
     * Required for serialization support.
     * 
     * @see java.io.Serializable
     */
    private static final long serialVersionUID = 1L;

    /**
     * Constructor error message.
     */
    private transient static final String MUST_BE_THROWABLE =
        "The Nestable implementation passed to the NestableDelegate(Nestable) "
            + "constructor must extend java.lang.Throwable";

    /**
     * Holds the reference to the exception or error that we're
     * wrapping (which must be a {@link
     * org.apache.commons.lang.exception.Nestable} implementation).
     */
    private Throwable nestable = null;
    
    /**
     * Whether to print the stack trace top-down.
     * This public flag may be set by calling code, typically in initialisation.
     * This exists for backwards compatability, setting it to false will return
     * the library to v1.0 behaviour (but will affect all users of the library
     * in the classloader).
     * @since 2.0
     */
    public static boolean topDown = true;
    
    /**
     * Whether to trim the repeated stack trace.
     * This public flag may be set by calling code, typically in initialisation.
     * This exists for backwards compatability, setting it to false will return
     * the library to v1.0 behaviour (but will affect all users of the library
     * in the classloader).
     * @since 2.0
     */
    public static boolean trimStackFrames = true;
    
    /**
     * Whether to match subclasses via indexOf.
     * This public flag may be set by calling code, typically in initialisation.
     * This exists for backwards compatability, setting it to false will return
     * the library to v2.0 behaviour (but will affect all users of the library
     * in the classloader).
     * @since 2.1
     */
    public static boolean matchSubclasses = true;

    /**
     * Constructs a new <code>NestableDelegate</code> instance to manage the
     * specified <code>Nestable</code>.
     *
     * @param nestable the Nestable implementation (<i>must</i> extend
     * {@link java.lang.Throwable})
     * @since 2.0
     */
    public NestableDelegate(Nestable nestable) {
        if (nestable instanceof Throwable) {
            this.nestable = (Throwable) nestable;
        } else {
            throw new IllegalArgumentException(MUST_BE_THROWABLE);
        }
    }

    /**
     * Returns the error message of the <code>Throwable</code> in the chain of <code>Throwable</code>s at the
     * specified index, numbered from 0.
     * 
     * @param index
     *            the index of the <code>Throwable</code> in the chain of <code>Throwable</code>s
     * @return the error message, or null if the <code>Throwable</code> at the specified index in the chain does not
     *         contain a message
     * @throws IndexOutOfBoundsException
     *             if the <code>index</code> argument is negative or not less than the count of <code>Throwable</code>s
     *             in the chain
     * @since 2.0
     */
    public String getMessage(int index) {
        Throwable t = this.getThrowable(index);
        if (Nestable.class.isInstance(t)) {
            return ((Nestable) t).getMessage(0);
        }
        return t.getMessage();
    }

    /**
     * Returns the full message contained by the <code>Nestable</code> and any nested <code>Throwable</code>s.
     * 
     * @param baseMsg
     *            the base message to use when creating the full message. Should be generally be called via
     *            <code>nestableHelper.getMessage(super.getMessage())</code>, where <code>super</code> is an
     *            instance of {@link java.lang.Throwable}.
     * @return The concatenated message for this and all nested <code>Throwable</code>s
     * @since 2.0
     */
    public String getMessage(String baseMsg) {
        Throwable nestedCause = ExceptionUtils.getCause(this.nestable);
        String causeMsg = nestedCause == null ? null : nestedCause.getMessage();
        if (nestedCause == null || causeMsg == null) {
            return baseMsg; // may be null, which is a valid result
        }
        if (baseMsg == null) {
            return causeMsg;
        }
        return baseMsg + ": " + causeMsg;
    }

    /**
     * Returns the error message of this and any nested <code>Throwable</code>s in an array of Strings, one element
     * for each message. Any <code>Throwable</code> not containing a message is represented in the array by a null.
     * This has the effect of cause the length of the returned array to be equal to the result of the
     * {@link #getThrowableCount()} operation.
     * 
     * @return the error messages
     * @since 2.0
     */
    public String[] getMessages() {
        Throwable[] throwables = this.getThrowables();
        String[] msgs = new String[throwables.length];
        for (int i = 0; i < throwables.length; i++) {
            msgs[i] =
                (Nestable.class.isInstance(throwables[i])
                    ? ((Nestable) throwables[i]).getMessage(0)
                    : throwables[i].getMessage());
        }
        return msgs;
    }

    /**
     * Returns the <code>Throwable</code> in the chain of
     * <code>Throwable</code>s at the specified index, numbered from 0.
     *
     * @param index the index, numbered from 0, of the <code>Throwable</code> in
     * the chain of <code>Throwable</code>s
     * @return the <code>Throwable</code>
     * @throws IndexOutOfBoundsException if the <code>index</code> argument is
     * negative or not less than the count of <code>Throwable</code>s in the
     * chain
     * @since 2.0
     */
    public Throwable getThrowable(int index) {
        if (index == 0) {
            return this.nestable;
        }
        Throwable[] throwables = this.getThrowables();
        return throwables[index];
    }

    /**
     * Returns the number of <code>Throwable</code>s contained in the
     * <code>Nestable</code> contained by this delegate.
     *
     * @return the throwable count
     * @since 2.0
     */
    public int getThrowableCount() {
        return ExceptionUtils.getThrowableCount(this.nestable);
    }

    /**
     * Returns this delegate's <code>Nestable</code> and any nested
     * <code>Throwable</code>s in an array of <code>Throwable</code>s, one
     * element for each <code>Throwable</code>.
     *
     * @return the <code>Throwable</code>s
     * @since 2.0
     */
    public Throwable[] getThrowables() {
        return ExceptionUtils.getThrowables(this.nestable);
    }

    /**
     * Returns the index, numbered from 0, of the first <code>Throwable</code>
     * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
     * with an index greater than or equal to the specified index.
     * The method returns -1 if the specified type is not found in the chain.
     * <p>
     * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
     * such that this method matches subclasses.
     * If you want to NOT match subclasses, please use
     * {@link ExceptionUtils#indexOfThrowable(Throwable, Class, int)}
     * (which is avaiable in all versions of lang).
     * An alternative is to use the public static flag {@link #matchSubclasses}
     * on <code>NestableDelegate</code>, however this is not recommended.
     *
     * @param type  the type to find, subclasses match, null returns -1
     * @param fromIndex the index, numbered from 0, of the starting position in
     * the chain to be searched
     * @return index of the first occurrence of the type in the chain, or -1 if
     * the type is not found
     * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
     * is negative or not less than the count of <code>Throwable</code>s in the
     * chain
     * @since 2.0
     */
    public int indexOfThrowable(Class type, int fromIndex) {
        if (type == null) {
            return -1;
        }
        if (fromIndex < 0) {
            throw new IndexOutOfBoundsException("The start index was out of bounds: " + fromIndex);
        }
        Throwable[] throwables = ExceptionUtils.getThrowables(this.nestable);
        if (fromIndex >= throwables.length) {
            throw new IndexOutOfBoundsException("The start index was out of bounds: "
                + fromIndex + " >= " + throwables.length);
        }
        if (matchSubclasses) {
            for (int i = fromIndex; i < throwables.length; i++) {
                if (type.isAssignableFrom(throwables[i].getClass())) {
                    return i;
                }
            }
        } else {
            for (int i = fromIndex; i < throwables.length; i++) {
                if (type.equals(throwables[i].getClass())) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * Prints the stack trace of this exception the the standar error
     * stream.
     */
    public void printStackTrace() {
        printStackTrace(System.err);
    }

    /**
     * Prints the stack trace of this exception to the specified
     * stream.
     *
     * @param out <code>PrintStream</code> to use for output.
     * @see #printStackTrace(PrintWriter)
     */
    public void printStackTrace(PrintStream out) {
        synchronized (out) {
            PrintWriter pw = new PrintWriter(out, false);
            printStackTrace(pw);
            // Flush the PrintWriter before it's GC'ed.
            pw.flush();
        }
    }

    /**
     * Prints the stack trace of this exception to the specified
     * writer. If the Throwable class has a <code>getCause</code>
     * method (i.e. running on jre1.4 or higher), this method just 
     * uses Throwable's printStackTrace() method. Otherwise, generates
     * the stack-trace, by taking into account the 'topDown' and 
     * 'trimStackFrames' parameters. The topDown and trimStackFrames 
     * are set to 'true' by default (produces jre1.4-like stack trace).
     *
     * @param out <code>PrintWriter</code> to use for output.
     */
    public void printStackTrace(PrintWriter out) {
        Throwable throwable = this.nestable;
        // if running on jre1.4 or higher, use default printStackTrace
        if (ExceptionUtils.isThrowableNested()) {
            if (throwable instanceof Nestable) {
                ((Nestable)throwable).printPartialStackTrace(out);
            } else {
                throwable.printStackTrace(out);
            }
            return;
        }

        // generating the nested stack trace
        List stacks = new ArrayList();
        while (throwable != null) {
            String[] st = getStackFrames(throwable);
            stacks.add(st);
            throwable = ExceptionUtils.getCause(throwable);
        }

        // If NOT topDown, reverse the stack
        String separatorLine = "Caused by: ";
        if (!topDown) {
            separatorLine = "Rethrown as: ";
            Collections.reverse(stacks);
        }

        // Remove the repeated lines in the stack
        if (trimStackFrames) {
          trimStackFrames(stacks);
        }

        synchronized (out) {
            for (Iterator iter=stacks.iterator(); iter.hasNext();) {
                String[] st = (String[]) iter.next();
                for (int i=0, len=st.length; i < len; i++) {
                    out.println(st[i]);
                }
                if (iter.hasNext()) {
                    out.print(separatorLine);
                }
            }
        }
    }

    /**
     * Captures the stack trace associated with the specified
     * <code>Throwable</code> object, decomposing it into a list of
     * stack frames.
     *
     * @param t The <code>Throwable</code>.
     * @return  An array of strings describing each stack frame.
     * @since 2.0
     */
    protected String[] getStackFrames(Throwable t) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);

        // Avoid infinite loop between decompose() and printStackTrace().
        if (t instanceof Nestable) {
            ((Nestable) t).printPartialStackTrace(pw);
        } else {
            t.printStackTrace(pw);
        }
        return ExceptionUtils.getStackFrames(sw.getBuffer().toString());
    }
    
    /**
     * Trims the stack frames. The first set is left untouched. The rest
     * of the frames are truncated from the bottom by comparing with
     * one just on top.
     *
     * @param stacks The list containing String[] elements
     * @since 2.0
     */
    protected void trimStackFrames(List stacks) {
         for (int size=stacks.size(), i=size-1; i > 0; i--) {
             String[] curr = (String[]) stacks.get(i);
             String[] next = (String[]) stacks.get(i-1); 
             
             List currList = new ArrayList(Arrays.asList(curr));
             List nextList = new ArrayList(Arrays.asList(next));
             ExceptionUtils.removeCommonFrames(currList, nextList);

             int trimmed = curr.length - currList.size();
             if (trimmed > 0) {
                 currList.add("\t... "+trimmed+" more");
                 stacks.set(
                     i, 
                     currList.toArray(new String[currList.size()])
                 );
             }
         }
     }
}
