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

package com.google.common.flogger;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.Queue;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import com.google.common.flogger.util.Checks;

public abstract class LoggingScope
{
    private final String label;
    
    public static LoggingScope create(final String label) {
        return new WeakScope(Checks.checkNotNull(label, "label"));
    }
    
    protected LoggingScope(final String label) {
        this.label = label;
    }
    
    protected abstract LogSiteKey specialize(final LogSiteKey p0);
    
    protected abstract void onClose(final Runnable p0);
    
    @Override
    public final String toString() {
        return this.label;
    }
    
    static final class WeakScope extends LoggingScope
    {
        private final KeyPart keyPart;
        
        public WeakScope(final String label) {
            super(label);
            this.keyPart = new KeyPart(this);
        }
        
        @Override
        protected LogSiteKey specialize(final LogSiteKey key) {
            return SpecializedLogSiteKey.of(key, this.keyPart);
        }
        
        @Override
        protected void onClose(final Runnable remove) {
            KeyPart.removeUnusedKeys();
            this.keyPart.onCloseHooks.offer(remove);
        }
        
        void closeForTesting() {
            this.keyPart.close();
        }
        
        private static class KeyPart extends WeakReference<LoggingScope>
        {
            private static final ReferenceQueue<LoggingScope> queue;
            private final Queue<Runnable> onCloseHooks;
            
            KeyPart(final LoggingScope scope) {
                super(scope, KeyPart.queue);
                this.onCloseHooks = new ConcurrentLinkedQueue<Runnable>();
            }
            
            static void removeUnusedKeys() {
                for (KeyPart p = (KeyPart)KeyPart.queue.poll(); p != null; p = (KeyPart)KeyPart.queue.poll()) {
                    p.close();
                }
            }
            
            private void close() {
                for (Runnable r = this.onCloseHooks.poll(); r != null; r = this.onCloseHooks.poll()) {
                    r.run();
                }
            }
            
            static {
                queue = new ReferenceQueue<LoggingScope>();
            }
        }
    }
}
