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

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

// exceptions that are known to wrap other exceptions
import java.lang.reflect.InvocationTargetException;

/**
 * A utility for wrapping exceptions.
 */
public class ExceptionUtil 
{
    /**
     * List of no-arg methods that are known to return a wrapped throwable
     **/
    private static final String[] unwrapMethods = { "getRootCause", "getTargetException", 
                                             "getTargetError", "getException", 
                                             "getCausedByException", "getLinkedException" };

	public static Throwable wrappedException(Throwable t)
	{
		// handle these statically since they are core to Java
		if (t instanceof InvocationTargetException)
		{
			return ((InvocationTargetException)t).getTargetException();
		}
        
		return getRootCauseWithReflection(t);
	}

    /**
     * Get to the base exception (if any)
     */
    public static Throwable baseException(Throwable t) {
        Throwable wrapped = wrappedException(t);
        if (wrapped != null)
            return baseException(wrapped);
        else
	    return t;
    }

    /**
     * return the stack trace in a String
     */
    public static String toString(Throwable t) {
        StringWriter strWrt = new StringWriter();
        t.printStackTrace(new PrintWriter(strWrt));

        return strWrt.toString();
    }

    /**
     * return the stack trace up to the first line that starts with prefix
     *
     * Example: ExceptionUtil.getStackTraceUpTo(exception, "jrunx.");
     */
    public static String getStackTraceUpTo(Throwable t, String prefix) {
	StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
        
        StringBuilder trace = new StringBuilder();

        boolean done = false;

        String lookingFor = "at " + prefix;
        while (!done && tokens.hasMoreElements())
        {
            String token = tokens.nextToken();
            if (token.indexOf(lookingFor) == -1)
                trace.append(token);
            else
                done = true;
            trace.append("\n");
        }
        
        return trace.toString();
    }
    
    /**
     * return the top n lines of this stack trace
     *
     * Example: ExceptionUtil.getStackTraceLines(exception, 10);
     */
    public static String getStackTraceLines(Throwable t, int numLines) {
	StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
        
        StringBuilder trace = new StringBuilder();

        for (int i=0; i<numLines; i++)
        {
            String token = tokens.nextToken();
            trace.append(token);
            trace.append("\n");
        }
        
        return trace.toString();
    }

    /**
     * Return the "nth" method call from the stack trace of "t", where 0 is
     * the top.
     */
    public static String getCallAt(Throwable t, int nth) {
	StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
	try {
	    // Skip the first line - the exception message
	    for(int i = 0; i <= nth; ++i)
		tokens.nextToken();
            
            // get the method name from the next token
	    String token = tokens.nextToken();
	    int index1 = token.indexOf(' ');
	    int index2 = token.indexOf('(');
	    StringBuilder call = new StringBuilder();
	    call.append(token.substring(index1 < 0 ? 0 : index1 + 1, index2 < 0 ? call.length() : index2));

	    int index3 = token.indexOf(':', index2 < 0 ? 0 : index2);
	    if(index3 >= 0) {
		int index4 = token.indexOf(')', index3);
	        call.append(token.substring(index3, index4 < 0 ? token.length() : index4));
	    }
	    return call.toString();
	}
	catch(NoSuchElementException e) {}

	return "unknown";
    }
    

    /**
     * Utility method for converting an exception into a string. This
     * method unwinds all wrapped exceptions
     * @param t The throwable exception
     * @return The printable exception
     */
    public static String exceptionToString(Throwable t) 
    {
        StringWriter sw = new StringWriter();
        PrintWriter out = new PrintWriter(sw);

        //print out the exception stack.
        printExceptionStack(t, out, 0);
        return sw.toString();
    }

    /**
     * Recursively prints out a stack of wrapped exceptions.
     */
    protected static void printExceptionStack(Throwable th, PrintWriter out, int depth){
        //only print the stack depth if the depth is greater than 0
        boolean printStackDepth = depth>0;

        Throwable wrappedException = ExceptionUtil.wrappedException(th);
        if (wrappedException != null) 
        {
            printStackDepth = true;
            printExceptionStack(wrappedException, out, depth + 1);
        }
		
        if(printStackDepth){
            out.write("[" + depth + "]");
        }

        th.printStackTrace(out);
    }

    private static Throwable getRootCauseWithReflection(Throwable t)
    {
        for(int i = 0; i < unwrapMethods.length; i++)
        {
            Method m = null;

            try
            {
                m = t.getClass().getMethod(unwrapMethods[i], (Class[])null);
                return (Throwable) m.invoke(t, (Object[])null);
            }
            catch(Exception nsme)
            {
                // ignore
            }
        }
        
        return null;
    }
}
