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

package com.google.common.flogger.context;

import java.io.Closeable;
import com.google.errorprone.annotations.MustBeClosed;
import java.util.concurrent.Callable;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import com.google.common.flogger.LoggingScope;
import com.google.common.flogger.MetadataKey;
import com.google.common.flogger.util.Checks;
import com.google.errorprone.annotations.CheckReturnValue;

public abstract class ScopedLoggingContext
{
    @CheckReturnValue
    public static ScopedLoggingContext getInstance() {
        return ContextDataProvider.getInstance().getContextApiSingleton();
    }
    
    protected ScopedLoggingContext() {
    }
    
    @CheckReturnValue
    public abstract Builder newContext();
    
    @Deprecated
    @CheckReturnValue
    public Builder newScope() {
        return this.newContext();
    }
    
    public boolean addTags(final Tags tags) {
        Checks.checkNotNull(tags, "tags");
        return false;
    }
    
    public <T> boolean addMetadata(final MetadataKey<T> key, final T value) {
        Checks.checkNotNull(key, "key");
        Checks.checkNotNull(value, "value");
        return false;
    }
    
    public boolean applyLogLevelMap(final LogLevelMap logLevelMap) {
        Checks.checkNotNull(logLevelMap, "log level map");
        return false;
    }
    
    private static void closeAndMaybePropagateError(final LoggingContextCloseable context, final boolean callerHasError) {
        try {
            context.close();
        }
        catch (final RuntimeException e) {
            if (!callerHasError) {
                throw (e instanceof InvalidLoggingContextStateException) ? e : new InvalidLoggingContextStateException("invalid logging context state", e);
            }
        }
    }
    
    public static final class ScopeList
    {
        private final ScopeType key;
        private final LoggingScope scope;
        @NullableDecl
        private final ScopeList next;
        
        @NullableDecl
        public static ScopeList addScope(@NullableDecl final ScopeList list, @NullableDecl final ScopeType type) {
            return (type != null && lookup(list, type) == null) ? new ScopeList(type, type.newScope(), list) : list;
        }
        
        @NullableDecl
        public static LoggingScope lookup(@NullableDecl ScopeList list, final ScopeType type) {
            while (list != null) {
                if (type.equals(list.key)) {
                    return list.scope;
                }
                list = list.next;
            }
            return null;
        }
        
        public ScopeList(final ScopeType key, final LoggingScope scope, @NullableDecl final ScopeList next) {
            this.key = Checks.checkNotNull(key, "scope type");
            this.scope = Checks.checkNotNull(scope, "scope");
            this.next = next;
        }
    }
    
    public abstract static class Builder
    {
        private Tags tags;
        private ScopeMetadata.Builder metadata;
        private LogLevelMap logLevelMap;
        
        protected Builder() {
            this.tags = null;
            this.metadata = null;
            this.logLevelMap = null;
        }
        
        @CheckReturnValue
        public final Builder withTags(final Tags tags) {
            Checks.checkState(this.tags == null, "tags already set");
            Checks.checkNotNull(tags, "tags");
            this.tags = tags;
            return this;
        }
        
        @CheckReturnValue
        public final <T> Builder withMetadata(final MetadataKey<T> key, final T value) {
            if (this.metadata == null) {
                this.metadata = ScopeMetadata.builder();
            }
            this.metadata.add(key, value);
            return this;
        }
        
        @CheckReturnValue
        public final Builder withLogLevelMap(final LogLevelMap logLevelMap) {
            Checks.checkState(this.logLevelMap == null, "log level map already set");
            Checks.checkNotNull(logLevelMap, "log level map");
            this.logLevelMap = logLevelMap;
            return this;
        }
        
        @CheckReturnValue
        public final Runnable wrap(final Runnable r) {
            return new Runnable() {
                @Override
                public void run() {
                    final LoggingContextCloseable context = Builder.this.install();
                    boolean hasError = true;
                    try {
                        r.run();
                        hasError = false;
                    }
                    finally {
                        closeAndMaybePropagateError(context, hasError);
                    }
                }
            };
        }
        
        @CheckReturnValue
        public final <R> Callable<R> wrap(final Callable<R> c) {
            return new Callable<R>() {
                @Override
                public R call() throws Exception {
                    final LoggingContextCloseable context = Builder.this.install();
                    boolean hasError = true;
                    try {
                        final R result = c.call();
                        hasError = false;
                        return result;
                    }
                    finally {
                        closeAndMaybePropagateError(context, hasError);
                    }
                }
            };
        }
        
        public final void run(final Runnable r) {
            this.wrap(r).run();
        }
        
        public final <R> R call(final Callable<R> c) throws Exception {
            return this.wrap(c).call();
        }
        
        public final <R> R callUnchecked(final Callable<R> c) {
            try {
                return (R)this.call((Callable<Object>)c);
            }
            catch (final RuntimeException e) {
                throw e;
            }
            catch (final Exception e2) {
                throw new RuntimeException("checked exception caught during context call", e2);
            }
        }
        
        @CheckReturnValue
        @MustBeClosed
        public abstract LoggingContextCloseable install();
        
        @NullableDecl
        protected final Tags getTags() {
            return this.tags;
        }
        
        @NullableDecl
        protected final ScopeMetadata getMetadata() {
            return (this.metadata != null) ? this.metadata.build() : null;
        }
        
        @NullableDecl
        protected final LogLevelMap getLogLevelMap() {
            return this.logLevelMap;
        }
    }
    
    public static final class InvalidLoggingContextStateException extends IllegalStateException
    {
        public InvalidLoggingContextStateException(final String message, final Throwable cause) {
            super(message, cause);
        }
        
        public InvalidLoggingContextStateException(final String message) {
            super(message);
        }
    }
    
    public interface LoggingContextCloseable extends Closeable
    {
        void close();
    }
}
