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

package io.sentry.protocol;

import io.sentry.vendor.gson.stream.JsonToken;
import io.sentry.ObjectReader;
import io.sentry.JsonDeserializer;
import java.io.IOException;
import java.util.List;
import java.util.Collections;
import io.sentry.ILogger;
import io.sentry.ObjectWriter;
import java.util.HashMap;
import java.util.Set;
import java.util.Enumeration;
import io.sentry.ISentryLifecycleToken;
import io.sentry.util.HintUtils;
import io.sentry.util.Objects;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import io.sentry.ProfileContext;
import io.sentry.SpanContext;
import java.util.Map;
import io.sentry.util.AutoClosableReentrantLock;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ConcurrentHashMap;
import io.sentry.JsonSerializable;

public class Contexts implements JsonSerializable
{
    private static final long serialVersionUID = 252445813254943011L;
    public static final String REPLAY_ID = "replay_id";
    @NotNull
    private final ConcurrentHashMap<String, Object> internalStorage;
    @NotNull
    protected final AutoClosableReentrantLock responseLock;
    
    public Contexts() {
        this.internalStorage = new ConcurrentHashMap<String, Object>();
        this.responseLock = new AutoClosableReentrantLock();
    }
    
    public Contexts(@NotNull final Contexts contexts) {
        this.internalStorage = new ConcurrentHashMap<String, Object>();
        this.responseLock = new AutoClosableReentrantLock();
        for (final Map.Entry<String, Object> entry : contexts.entrySet()) {
            if (entry != null) {
                final Object value = entry.getValue();
                if ("app".equals(entry.getKey()) && value instanceof App) {
                    this.setApp(new App((App)value));
                }
                else if ("browser".equals(entry.getKey()) && value instanceof Browser) {
                    this.setBrowser(new Browser((Browser)value));
                }
                else if ("device".equals(entry.getKey()) && value instanceof Device) {
                    this.setDevice(new Device((Device)value));
                }
                else if ("os".equals(entry.getKey()) && value instanceof OperatingSystem) {
                    this.setOperatingSystem(new OperatingSystem((OperatingSystem)value));
                }
                else if ("runtime".equals(entry.getKey()) && value instanceof SentryRuntime) {
                    this.setRuntime(new SentryRuntime((SentryRuntime)value));
                }
                else if ("feedback".equals(entry.getKey()) && value instanceof Feedback) {
                    this.setFeedback(new Feedback((Feedback)value));
                }
                else if ("gpu".equals(entry.getKey()) && value instanceof Gpu) {
                    this.setGpu(new Gpu((Gpu)value));
                }
                else if ("trace".equals(entry.getKey()) && value instanceof SpanContext) {
                    this.setTrace(new SpanContext((SpanContext)value));
                }
                else if ("profile".equals(entry.getKey()) && value instanceof ProfileContext) {
                    this.setProfile(new ProfileContext((ProfileContext)value));
                }
                else if ("response".equals(entry.getKey()) && value instanceof Response) {
                    this.setResponse(new Response((Response)value));
                }
                else if ("spring".equals(entry.getKey()) && value instanceof Spring) {
                    this.setSpring(new Spring((Spring)value));
                }
                else {
                    this.put(entry.getKey(), value);
                }
            }
        }
    }
    
    @Nullable
    private <T> T toContextType(@NotNull final String key, @NotNull final Class<T> clazz) {
        final Object item = this.get(key);
        return clazz.isInstance(item) ? clazz.cast(item) : null;
    }
    
    @Nullable
    public SpanContext getTrace() {
        return this.toContextType("trace", SpanContext.class);
    }
    
    public void setTrace(@NotNull final SpanContext traceContext) {
        Objects.requireNonNull(traceContext, "traceContext is required");
        this.put("trace", traceContext);
    }
    
    @Nullable
    public ProfileContext getProfile() {
        return this.toContextType("profile", ProfileContext.class);
    }
    
    public void setProfile(@Nullable final ProfileContext profileContext) {
        Objects.requireNonNull(profileContext, "profileContext is required");
        this.put("profile", profileContext);
    }
    
    @Nullable
    public App getApp() {
        return this.toContextType("app", App.class);
    }
    
    public void setApp(@NotNull final App app) {
        this.put("app", app);
    }
    
    @Nullable
    public Browser getBrowser() {
        return this.toContextType("browser", Browser.class);
    }
    
    public void setBrowser(@NotNull final Browser browser) {
        this.put("browser", browser);
    }
    
    @Nullable
    public Device getDevice() {
        return this.toContextType("device", Device.class);
    }
    
    public void setDevice(@NotNull final Device device) {
        this.put("device", device);
    }
    
    @Nullable
    public OperatingSystem getOperatingSystem() {
        return this.toContextType("os", OperatingSystem.class);
    }
    
    public void setOperatingSystem(@NotNull final OperatingSystem operatingSystem) {
        this.put("os", operatingSystem);
    }
    
    @Nullable
    public SentryRuntime getRuntime() {
        return this.toContextType("runtime", SentryRuntime.class);
    }
    
    public void setRuntime(@NotNull final SentryRuntime runtime) {
        this.put("runtime", runtime);
    }
    
    @Nullable
    public Feedback getFeedback() {
        return this.toContextType("feedback", Feedback.class);
    }
    
    public void setFeedback(@NotNull final Feedback feedback) {
        this.put("feedback", feedback);
    }
    
    @Nullable
    public Gpu getGpu() {
        return this.toContextType("gpu", Gpu.class);
    }
    
    public void setGpu(@NotNull final Gpu gpu) {
        this.put("gpu", gpu);
    }
    
    @Nullable
    public Response getResponse() {
        return this.toContextType("response", Response.class);
    }
    
    public void withResponse(final HintUtils.SentryConsumer<Response> callback) {
        try (final ISentryLifecycleToken ignored = this.responseLock.acquire()) {
            final Response response = this.getResponse();
            if (response != null) {
                callback.accept(response);
            }
            else {
                final Response newResponse = new Response();
                this.setResponse(newResponse);
                callback.accept(newResponse);
            }
        }
    }
    
    public void setResponse(@NotNull final Response response) {
        try (final ISentryLifecycleToken ignored = this.responseLock.acquire()) {
            this.put("response", response);
        }
    }
    
    @Nullable
    public Spring getSpring() {
        return this.toContextType("spring", Spring.class);
    }
    
    public void setSpring(@NotNull final Spring spring) {
        this.put("spring", spring);
    }
    
    @Nullable
    public FeatureFlags getFeatureFlags() {
        return this.toContextType("flags", FeatureFlags.class);
    }
    
    public void setFeatureFlags(@NotNull final FeatureFlags featureFlags) {
        this.put("flags", featureFlags);
    }
    
    public int size() {
        return this.internalStorage.size();
    }
    
    public int getSize() {
        return this.size();
    }
    
    public boolean isEmpty() {
        return this.internalStorage.isEmpty();
    }
    
    public boolean containsKey(@Nullable final Object key) {
        return key != null && this.internalStorage.containsKey(key);
    }
    
    @Nullable
    public Object get(@Nullable final Object key) {
        if (key == null) {
            return null;
        }
        return this.internalStorage.get(key);
    }
    
    @Nullable
    public Object put(@Nullable final String key, @Nullable final Object value) {
        if (key == null) {
            return null;
        }
        if (value == null) {
            return this.internalStorage.remove(key);
        }
        return this.internalStorage.put(key, value);
    }
    
    @Nullable
    public Object set(@Nullable final String key, @Nullable final Object value) {
        return this.put(key, value);
    }
    
    @Nullable
    public Object remove(@Nullable final Object key) {
        if (key == null) {
            return null;
        }
        return this.internalStorage.remove(key);
    }
    
    @NotNull
    public Enumeration<String> keys() {
        return this.internalStorage.keys();
    }
    
    @NotNull
    public Set<Map.Entry<String, Object>> entrySet() {
        return this.internalStorage.entrySet();
    }
    
    public void putAll(@Nullable final Map<? extends String, ?> m) {
        if (m == null) {
            return;
        }
        final Map<String, Object> tmpMap = new HashMap<String, Object>();
        for (final Map.Entry<? extends String, ?> entry : m.entrySet()) {
            if (entry.getKey() != null && entry.getValue() != null) {
                tmpMap.put((String)entry.getKey(), entry.getValue());
            }
        }
        this.internalStorage.putAll(tmpMap);
    }
    
    public void putAll(@Nullable final Contexts contexts) {
        if (contexts == null) {
            return;
        }
        this.internalStorage.putAll(contexts.internalStorage);
    }
    
    @Override
    public boolean equals(@Nullable final Object obj) {
        if (obj != null && obj instanceof Contexts) {
            final Contexts otherContexts = (Contexts)obj;
            return this.internalStorage.equals(otherContexts.internalStorage);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return this.internalStorage.hashCode();
    }
    
    @Override
    public void serialize(@NotNull final ObjectWriter writer, @NotNull final ILogger logger) throws IOException {
        writer.beginObject();
        final List<String> sortedKeys = Collections.list(this.keys());
        Collections.sort(sortedKeys);
        for (final String key : sortedKeys) {
            final Object value = this.get(key);
            if (value != null) {
                writer.name(key).value(logger, value);
            }
        }
        writer.endObject();
    }
    
    public static final class Deserializer implements JsonDeserializer<Contexts>
    {
        @NotNull
        @Override
        public Contexts deserialize(@NotNull final ObjectReader reader, @NotNull final ILogger logger) throws Exception {
            final Contexts contexts = new Contexts();
            reader.beginObject();
            while (reader.peek() == JsonToken.NAME) {
                final String nextName2;
                final String nextName = nextName2 = reader.nextName();
                switch (nextName2) {
                    case "app": {
                        contexts.setApp(new App.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "browser": {
                        contexts.setBrowser(new Browser.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "device": {
                        contexts.setDevice(new Device.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "gpu": {
                        contexts.setGpu(new Gpu.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "os": {
                        contexts.setOperatingSystem(new OperatingSystem.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "runtime": {
                        contexts.setRuntime(new SentryRuntime.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "feedback": {
                        contexts.setFeedback(new Feedback.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "trace": {
                        contexts.setTrace(new SpanContext.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "profile": {
                        contexts.setProfile(new ProfileContext.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "response": {
                        contexts.setResponse(new Response.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "spring": {
                        contexts.setSpring(new Spring.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    case "flags": {
                        contexts.setFeatureFlags(new FeatureFlags.Deserializer().deserialize(reader, logger));
                        continue;
                    }
                    default: {
                        final Object object = reader.nextObjectOrNull();
                        if (object != null) {
                            contexts.put(nextName, object);
                            continue;
                        }
                        continue;
                    }
                }
            }
            reader.endObject();
            return contexts;
        }
    }
}
