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

package io.sentry;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
import io.sentry.hints.Enqueable;
import io.sentry.hints.Flushable;
import io.sentry.hints.SubmissionResult;
import io.sentry.hints.Retryable;
import io.sentry.hints.Cached;
import io.sentry.transport.RateLimiter;
import io.sentry.util.HintUtils;
import java.io.File;
import java.util.Queue;
import org.jetbrains.annotations.NotNull;

abstract class DirectoryProcessor
{
    private static final long ENVELOPE_PROCESSING_DELAY = 100L;
    @NotNull
    private final IScopes scopes;
    @NotNull
    private final ILogger logger;
    private final long flushTimeoutMillis;
    private final Queue<String> processedEnvelopes;
    
    DirectoryProcessor(@NotNull final IScopes scopes, @NotNull final ILogger logger, final long flushTimeoutMillis, final int maxQueueSize) {
        this.scopes = scopes;
        this.logger = logger;
        this.flushTimeoutMillis = flushTimeoutMillis;
        this.processedEnvelopes = (Queue<String>)SynchronizedQueue.synchronizedQueue(new CircularFifoQueue<Object>(maxQueueSize));
    }
    
    public void processDirectory(@NotNull final File directory) {
        try {
            this.logger.log(SentryLevel.DEBUG, "Processing dir. %s", directory.getAbsolutePath());
            final File[] filteredListFiles = directory.listFiles((d, name) -> this.isRelevantFileName(name));
            if (filteredListFiles == null) {
                this.logger.log(SentryLevel.ERROR, "Cache dir %s is null or is not a directory.", directory.getAbsolutePath());
                return;
            }
            this.logger.log(SentryLevel.DEBUG, "Processing %d items from cache dir %s", filteredListFiles.length, directory.getAbsolutePath());
            for (final File file : filteredListFiles) {
                if (!file.isFile()) {
                    this.logger.log(SentryLevel.DEBUG, "File %s is not a File.", file.getAbsolutePath());
                }
                else {
                    final String filePath = file.getAbsolutePath();
                    if (this.processedEnvelopes.contains(filePath)) {
                        this.logger.log(SentryLevel.DEBUG, "File '%s' has already been processed so it will not be processed again.", filePath);
                    }
                    else {
                        final RateLimiter rateLimiter = this.scopes.getRateLimiter();
                        if (rateLimiter != null && rateLimiter.isActiveForCategory(DataCategory.All)) {
                            this.logger.log(SentryLevel.INFO, "DirectoryProcessor, rate limiting active.", new Object[0]);
                            return;
                        }
                        this.logger.log(SentryLevel.DEBUG, "Processing file: %s", filePath);
                        final SendCachedEnvelopeHint cachedHint = new SendCachedEnvelopeHint(this.flushTimeoutMillis, this.logger, filePath, this.processedEnvelopes);
                        final Hint hint = HintUtils.createWithTypeCheckHint(cachedHint);
                        this.processFile(file, hint);
                        Thread.sleep(100L);
                    }
                }
            }
        }
        catch (final Throwable e) {
            this.logger.log(SentryLevel.ERROR, e, "Failed processing '%s'", directory.getAbsolutePath());
        }
    }
    
    protected abstract void processFile(@NotNull final File p0, @NotNull final Hint p1);
    
    protected abstract boolean isRelevantFileName(final String p0);
    
    private static final class SendCachedEnvelopeHint implements Cached, Retryable, SubmissionResult, Flushable, Enqueable
    {
        boolean retry;
        boolean succeeded;
        private final CountDownLatch latch;
        private final long flushTimeoutMillis;
        @NotNull
        private final ILogger logger;
        @NotNull
        private final String filePath;
        @NotNull
        private final Queue<String> processedEnvelopes;
        
        public SendCachedEnvelopeHint(final long flushTimeoutMillis, @NotNull final ILogger logger, @NotNull final String filePath, @NotNull final Queue<String> processedEnvelopes) {
            this.retry = false;
            this.succeeded = false;
            this.flushTimeoutMillis = flushTimeoutMillis;
            this.filePath = filePath;
            this.processedEnvelopes = processedEnvelopes;
            this.latch = new CountDownLatch(1);
            this.logger = logger;
        }
        
        @Override
        public boolean isRetry() {
            return this.retry;
        }
        
        @Override
        public void setRetry(final boolean retry) {
            this.retry = retry;
        }
        
        @Override
        public boolean waitFlush() {
            try {
                return this.latch.await(this.flushTimeoutMillis, TimeUnit.MILLISECONDS);
            }
            catch (final InterruptedException e) {
                Thread.currentThread().interrupt();
                this.logger.log(SentryLevel.ERROR, "Exception while awaiting on lock.", e);
                return false;
            }
        }
        
        @Override
        public void setResult(final boolean succeeded) {
            this.succeeded = succeeded;
            this.latch.countDown();
        }
        
        @Override
        public boolean isSuccess() {
            return this.succeeded;
        }
        
        @Override
        public void markEnqueued() {
            this.processedEnvelopes.add(this.filePath);
        }
    }
}
