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

package io.sentry.backpressure;

import io.sentry.ISentryExecutorService;
import java.util.concurrent.RejectedExecutionException;
import io.sentry.SentryLevel;
import io.sentry.ISentryLifecycleToken;
import io.sentry.util.AutoClosableReentrantLock;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.Future;
import io.sentry.IScopes;
import org.jetbrains.annotations.NotNull;
import io.sentry.SentryOptions;

public final class BackpressureMonitor implements IBackpressureMonitor, Runnable
{
    static final int MAX_DOWNSAMPLE_FACTOR = 10;
    private static final int INITIAL_CHECK_DELAY_IN_MS = 500;
    private static final int CHECK_INTERVAL_IN_MS = 10000;
    @NotNull
    private final SentryOptions sentryOptions;
    @NotNull
    private final IScopes scopes;
    private int downsampleFactor;
    @Nullable
    private volatile Future<?> latestScheduledRun;
    @NotNull
    private final AutoClosableReentrantLock lock;
    
    public BackpressureMonitor(@NotNull final SentryOptions sentryOptions, @NotNull final IScopes scopes) {
        this.downsampleFactor = 0;
        this.latestScheduledRun = null;
        this.lock = new AutoClosableReentrantLock();
        this.sentryOptions = sentryOptions;
        this.scopes = scopes;
    }
    
    @Override
    public void start() {
        this.reschedule(500);
    }
    
    @Override
    public void run() {
        this.checkHealth();
        this.reschedule(10000);
    }
    
    @Override
    public int getDownsampleFactor() {
        return this.downsampleFactor;
    }
    
    @Override
    public void close() {
        final Future<?> currentRun = this.latestScheduledRun;
        if (currentRun != null) {
            try (final ISentryLifecycleToken ignored = this.lock.acquire()) {
                currentRun.cancel(true);
            }
        }
    }
    
    void checkHealth() {
        if (this.isHealthy()) {
            if (this.downsampleFactor > 0) {
                this.sentryOptions.getLogger().log(SentryLevel.DEBUG, "Health check positive, reverting to normal sampling.", new Object[0]);
            }
            this.downsampleFactor = 0;
        }
        else if (this.downsampleFactor < 10) {
            ++this.downsampleFactor;
            this.sentryOptions.getLogger().log(SentryLevel.DEBUG, "Health check negative, downsampling with a factor of %d", this.downsampleFactor);
        }
    }
    
    private void reschedule(final int delay) {
        final ISentryExecutorService executorService = this.sentryOptions.getExecutorService();
        if (!executorService.isClosed()) {
            try (final ISentryLifecycleToken ignored = this.lock.acquire()) {
                try {
                    this.latestScheduledRun = executorService.schedule(this, delay);
                }
                catch (final RejectedExecutionException e) {
                    this.sentryOptions.getLogger().log(SentryLevel.WARNING, "Backpressure monitor reschedule task rejected", e);
                }
            }
        }
    }
    
    private boolean isHealthy() {
        return this.scopes.isHealthy();
    }
}
