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

package io.sentry;

import org.jetbrains.annotations.VisibleForTesting;
import java.io.IOException;
import io.sentry.hints.Cached;
import java.util.List;
import io.sentry.hints.AbnormalExit;
import java.util.ArrayList;
import io.sentry.protocol.SentryException;
import io.sentry.protocol.User;
import java.util.Iterator;
import java.util.HashMap;
import io.sentry.protocol.SdkVersion;
import io.sentry.protocol.SentryTransaction;
import io.sentry.util.HintUtils;
import java.util.Map;
import io.sentry.protocol.DebugMeta;
import io.sentry.util.Objects;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.ApiStatus;
import java.io.Closeable;

@ApiStatus.Internal
public final class MainEventProcessor implements EventProcessor, Closeable
{
    @NotNull
    private final SentryOptions options;
    @NotNull
    private final SentryThreadFactory sentryThreadFactory;
    @NotNull
    private final SentryExceptionFactory sentryExceptionFactory;
    @Nullable
    private volatile HostnameCache hostnameCache;
    
    public MainEventProcessor(@NotNull final SentryOptions options) {
        this.hostnameCache = null;
        this.options = Objects.requireNonNull(options, "The SentryOptions is required.");
        final SentryStackTraceFactory sentryStackTraceFactory = new SentryStackTraceFactory(this.options);
        this.sentryExceptionFactory = new SentryExceptionFactory(sentryStackTraceFactory);
        this.sentryThreadFactory = new SentryThreadFactory(sentryStackTraceFactory);
    }
    
    MainEventProcessor(@NotNull final SentryOptions options, @NotNull final SentryThreadFactory sentryThreadFactory, @NotNull final SentryExceptionFactory sentryExceptionFactory) {
        this.hostnameCache = null;
        this.options = Objects.requireNonNull(options, "The SentryOptions is required.");
        this.sentryThreadFactory = Objects.requireNonNull(sentryThreadFactory, "The SentryThreadFactory is required.");
        this.sentryExceptionFactory = Objects.requireNonNull(sentryExceptionFactory, "The SentryExceptionFactory is required.");
    }
    
    @NotNull
    @Override
    public SentryEvent process(@NotNull final SentryEvent event, @NotNull final Hint hint) {
        this.setCommons(event);
        this.setExceptions(event);
        this.setDebugMeta(event);
        this.setModules(event);
        if (this.shouldApplyScopeData(event, hint)) {
            this.processNonCachedEvent(event);
            this.setThreads(event, hint);
        }
        return event;
    }
    
    private void setDebugMeta(@NotNull final SentryBaseEvent event) {
        final DebugMeta debugMeta = DebugMeta.buildDebugMeta(event.getDebugMeta(), this.options);
        if (debugMeta != null) {
            event.setDebugMeta(debugMeta);
        }
    }
    
    private void setModules(@NotNull final SentryEvent event) {
        final Map<String, String> modules = this.options.getModulesLoader().getOrLoadModules();
        if (modules == null) {
            return;
        }
        final Map<String, String> eventModules = event.getModules();
        if (eventModules == null) {
            event.setModules(modules);
        }
        else {
            eventModules.putAll(modules);
        }
    }
    
    private boolean shouldApplyScopeData(@NotNull final SentryBaseEvent event, @NotNull final Hint hint) {
        if (HintUtils.shouldApplyScopeData(hint)) {
            return true;
        }
        this.options.getLogger().log(SentryLevel.DEBUG, "Event was cached so not applying data relevant to the current app execution/version: %s", event.getEventId());
        return false;
    }
    
    private void processNonCachedEvent(@NotNull final SentryBaseEvent event) {
        this.setRelease(event);
        this.setEnvironment(event);
        this.setServerName(event);
        this.setDist(event);
        this.setSdk(event);
        this.setTags(event);
        this.mergeUser(event);
    }
    
    @NotNull
    @Override
    public SentryTransaction process(@NotNull final SentryTransaction transaction, @NotNull final Hint hint) {
        this.setCommons(transaction);
        this.setDebugMeta(transaction);
        if (this.shouldApplyScopeData(transaction, hint)) {
            this.processNonCachedEvent(transaction);
        }
        return transaction;
    }
    
    @NotNull
    @Override
    public SentryReplayEvent process(@NotNull final SentryReplayEvent event, @NotNull final Hint hint) {
        this.setCommons(event);
        if (this.shouldApplyScopeData(event, hint)) {
            this.processNonCachedEvent(event);
            final SdkVersion replaySdkVersion = this.options.getSessionReplay().getSdkVersion();
            if (replaySdkVersion != null) {
                event.setSdk(replaySdkVersion);
            }
        }
        return event;
    }
    
    @Nullable
    @Override
    public SentryLogEvent process(@NotNull final SentryLogEvent event) {
        return event;
    }
    
    private void setCommons(@NotNull final SentryBaseEvent event) {
        this.setPlatform(event);
    }
    
    private void setPlatform(@NotNull final SentryBaseEvent event) {
        if (event.getPlatform() == null) {
            event.setPlatform("java");
        }
    }
    
    private void setRelease(@NotNull final SentryBaseEvent event) {
        if (event.getRelease() == null) {
            event.setRelease(this.options.getRelease());
        }
    }
    
    private void setEnvironment(@NotNull final SentryBaseEvent event) {
        if (event.getEnvironment() == null) {
            event.setEnvironment(this.options.getEnvironment());
        }
    }
    
    private void setServerName(@NotNull final SentryBaseEvent event) {
        if (event.getServerName() == null) {
            event.setServerName(this.options.getServerName());
        }
        if (this.options.isAttachServerName() && event.getServerName() == null) {
            this.ensureHostnameCache();
            if (this.hostnameCache != null) {
                event.setServerName(this.hostnameCache.getHostname());
            }
        }
    }
    
    private void ensureHostnameCache() {
        if (this.hostnameCache == null) {
            this.hostnameCache = HostnameCache.getInstance();
        }
    }
    
    private void setDist(@NotNull final SentryBaseEvent event) {
        if (event.getDist() == null) {
            event.setDist(this.options.getDist());
        }
    }
    
    private void setSdk(@NotNull final SentryBaseEvent event) {
        if (event.getSdk() == null) {
            event.setSdk(this.options.getSdkVersion());
        }
    }
    
    private void setTags(@NotNull final SentryBaseEvent event) {
        if (event.getTags() == null) {
            event.setTags(new HashMap<String, String>(this.options.getTags()));
        }
        else {
            for (final Map.Entry<String, String> item : this.options.getTags().entrySet()) {
                if (!event.getTags().containsKey(item.getKey())) {
                    event.setTag(item.getKey(), item.getValue());
                }
            }
        }
    }
    
    private void mergeUser(@NotNull final SentryBaseEvent event) {
        User user = event.getUser();
        if (user == null) {
            user = new User();
            event.setUser(user);
        }
        if (user.getIpAddress() == null && this.options.isSendDefaultPii()) {
            user.setIpAddress("{{auto}}");
        }
    }
    
    private void setExceptions(@NotNull final SentryEvent event) {
        final Throwable throwable = event.getThrowableMechanism();
        if (throwable != null) {
            event.setExceptions(this.sentryExceptionFactory.getSentryExceptions(throwable));
        }
    }
    
    private void setThreads(@NotNull final SentryEvent event, @NotNull final Hint hint) {
        if (event.getThreads() == null) {
            List<Long> mechanismThreadIds = null;
            final List<SentryException> eventExceptions = event.getExceptions();
            if (eventExceptions != null && !eventExceptions.isEmpty()) {
                for (final SentryException item : eventExceptions) {
                    if (item.getMechanism() != null && item.getThreadId() != null) {
                        if (mechanismThreadIds == null) {
                            mechanismThreadIds = new ArrayList<Long>();
                        }
                        mechanismThreadIds.add(item.getThreadId());
                    }
                }
            }
            if (this.options.isAttachThreads() || HintUtils.hasType(hint, AbnormalExit.class)) {
                final Object sentrySdkHint = HintUtils.getSentrySdkHint(hint);
                boolean ignoreCurrentThread = false;
                boolean attachStacktrace = this.options.isAttachStacktrace();
                if (sentrySdkHint instanceof AbnormalExit) {
                    ignoreCurrentThread = ((AbnormalExit)sentrySdkHint).ignoreCurrentThread();
                    attachStacktrace = true;
                }
                event.setThreads(this.sentryThreadFactory.getCurrentThreads(mechanismThreadIds, ignoreCurrentThread, attachStacktrace));
            }
            else if (this.options.isAttachStacktrace() && (eventExceptions == null || eventExceptions.isEmpty()) && !this.isCachedHint(hint)) {
                event.setThreads(this.sentryThreadFactory.getCurrentThread(this.options.isAttachStacktrace()));
            }
        }
    }
    
    private boolean isCachedHint(@NotNull final Hint hint) {
        return HintUtils.hasType(hint, Cached.class);
    }
    
    @Override
    public void close() throws IOException {
        if (this.hostnameCache != null) {
            this.hostnameCache.close();
        }
    }
    
    boolean isClosed() {
        return this.hostnameCache == null || this.hostnameCache.isClosed();
    }
    
    @VisibleForTesting
    @Nullable
    HostnameCache getHostnameCache() {
        return this.hostnameCache;
    }
    
    @Nullable
    @Override
    public Long getOrder() {
        return 0L;
    }
}
