// 
// Decompiled by Procyon v0.6.0
// 

package com.google.common.flogger.util;

import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import com.google.errorprone.annotations.CheckReturnValue;

@CheckReturnValue
public final class CallerFinder
{
    private static final FastStackGetter stackGetter;
    
    @NullableDecl
    public static StackTraceElement findCallerOf(final Class<?> target, final Throwable throwable, final int skip) {
        Checks.checkNotNull(target, "target");
        Checks.checkNotNull(throwable, "throwable");
        if (skip < 0) {
            throw new IllegalArgumentException("skip count cannot be negative: " + skip);
        }
        final StackTraceElement[] stack = (StackTraceElement[])((CallerFinder.stackGetter != null) ? null : throwable.getStackTrace());
        boolean foundCaller = false;
        try {
            int index = skip;
            StackTraceElement element;
            while (true) {
                element = ((CallerFinder.stackGetter != null) ? CallerFinder.stackGetter.getStackTraceElement(throwable, index) : stack[index]);
                if (target.getName().equals(element.getClassName())) {
                    foundCaller = true;
                }
                else if (foundCaller) {
                    break;
                }
                ++index;
            }
            return element;
        }
        catch (final Exception e) {
            return null;
        }
    }
    
    public static StackTraceElement[] getStackForCallerOf(final Class<?> target, final Throwable throwable, final int maxDepth, final int skip) {
        Checks.checkNotNull(target, "target");
        Checks.checkNotNull(throwable, "throwable");
        if (maxDepth <= 0 && maxDepth != -1) {
            throw new IllegalArgumentException("invalid maximum depth: " + maxDepth);
        }
        if (skip < 0) {
            throw new IllegalArgumentException("skip count cannot be negative: " + skip);
        }
        int depth;
        if (CallerFinder.stackGetter != null) {
            final StackTraceElement[] stack = null;
            depth = CallerFinder.stackGetter.getStackTraceDepth(throwable);
        }
        else {
            final StackTraceElement[] stack = throwable.getStackTrace();
            depth = stack.length;
        }
        boolean foundCaller = false;
        for (int index = skip; index < depth; ++index) {
            final StackTraceElement[] stack;
            final StackTraceElement element = (CallerFinder.stackGetter != null) ? CallerFinder.stackGetter.getStackTraceElement(throwable, index) : stack[index];
            if (target.getName().equals(element.getClassName())) {
                foundCaller = true;
            }
            else if (foundCaller) {
                int elementsToAdd = depth - index;
                if (maxDepth > 0 && maxDepth < elementsToAdd) {
                    elementsToAdd = maxDepth;
                }
                final StackTraceElement[] syntheticStack = new StackTraceElement[elementsToAdd];
                syntheticStack[0] = element;
                for (int n = 1; n < elementsToAdd; ++n) {
                    syntheticStack[n] = ((CallerFinder.stackGetter != null) ? CallerFinder.stackGetter.getStackTraceElement(throwable, index + n) : stack[index + n]);
                }
                return syntheticStack;
            }
        }
        return new StackTraceElement[0];
    }
    
    static {
        stackGetter = FastStackGetter.createIfSupported();
    }
}
