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

package io.sentry;

import java.io.Reader;
import java.io.StringReader;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.Charset;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public final class EnvelopeReader implements IEnvelopeReader
{
    private static final Charset UTF_8;
    @NotNull
    private final ISerializer serializer;
    
    public EnvelopeReader(@NotNull final ISerializer serializer) {
        this.serializer = serializer;
    }
    
    @Nullable
    @Override
    public SentryEnvelope read(@NotNull final InputStream stream) throws IOException {
        final byte[] buffer = new byte[1024];
        int streamOffset = 0;
        int envelopeEndHeaderOffset = -1;
        try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            int currentLength;
            while ((currentLength = stream.read(buffer)) > 0) {
                for (int i = 0; envelopeEndHeaderOffset == -1 && i < currentLength; ++i) {
                    if (buffer[i] == 10) {
                        envelopeEndHeaderOffset = streamOffset + i;
                        break;
                    }
                }
                outputStream.write(buffer, 0, currentLength);
                streamOffset += currentLength;
            }
            final byte[] envelopeBytes = outputStream.toByteArray();
            if (envelopeBytes.length == 0) {
                throw new IllegalArgumentException("Empty stream.");
            }
            if (envelopeEndHeaderOffset == -1) {
                throw new IllegalArgumentException("Envelope contains no header.");
            }
            final SentryEnvelopeHeader header = this.deserializeEnvelopeHeader(envelopeBytes, 0, envelopeEndHeaderOffset);
            if (header == null) {
                throw new IllegalArgumentException("Envelope header is null.");
            }
            int itemHeaderStartOffset = envelopeEndHeaderOffset + 1;
            final List<SentryEnvelopeItem> items = new ArrayList<SentryEnvelopeItem>();
            while (true) {
                int lineBreakIndex = -1;
                for (int j = itemHeaderStartOffset; j < envelopeBytes.length; ++j) {
                    if (envelopeBytes[j] == 10) {
                        lineBreakIndex = j;
                        break;
                    }
                }
                if (lineBreakIndex == -1) {
                    throw new IllegalArgumentException("Invalid envelope. Item at index '" + items.size() + "'. has no header delimiter.");
                }
                final SentryEnvelopeItemHeader itemHeader = this.deserializeEnvelopeItemHeader(envelopeBytes, itemHeaderStartOffset, lineBreakIndex - itemHeaderStartOffset);
                if (itemHeader == null || itemHeader.getLength() <= 0) {
                    throw new IllegalArgumentException("Item header at index '" + items.size() + "' is null or empty.");
                }
                final int payloadEndOffsetExclusive = lineBreakIndex + itemHeader.getLength() + 1;
                if (payloadEndOffsetExclusive > envelopeBytes.length) {
                    throw new IllegalArgumentException("Invalid length for item at index '" + items.size() + "'. Item is '" + payloadEndOffsetExclusive + "' bytes. There are '" + envelopeBytes.length + "' in the buffer.");
                }
                final byte[] envelopeItemBytes = Arrays.copyOfRange(envelopeBytes, lineBreakIndex + 1, payloadEndOffsetExclusive);
                final SentryEnvelopeItem item = new SentryEnvelopeItem(itemHeader, envelopeItemBytes);
                items.add(item);
                if (payloadEndOffsetExclusive == envelopeBytes.length) {
                    break;
                }
                if (payloadEndOffsetExclusive + 1 == envelopeBytes.length) {
                    if (envelopeBytes[payloadEndOffsetExclusive] == 10) {
                        break;
                    }
                    throw new IllegalArgumentException("Envelope has invalid data following an item.");
                }
                else {
                    itemHeaderStartOffset = payloadEndOffsetExclusive + 1;
                }
            }
            return new SentryEnvelope(header, items);
        }
    }
    
    @Nullable
    private SentryEnvelopeHeader deserializeEnvelopeHeader(@NotNull final byte[] buffer, final int offset, final int length) {
        final String json = new String(buffer, offset, length, EnvelopeReader.UTF_8);
        try (final StringReader reader = new StringReader(json)) {
            return this.serializer.deserialize(reader, SentryEnvelopeHeader.class);
        }
    }
    
    @Nullable
    private SentryEnvelopeItemHeader deserializeEnvelopeItemHeader(@NotNull final byte[] buffer, final int offset, final int length) {
        final String json = new String(buffer, offset, length, EnvelopeReader.UTF_8);
        try (final StringReader reader = new StringReader(json)) {
            return this.serializer.deserialize(reader, SentryEnvelopeItemHeader.class);
        }
    }
    
    static {
        UTF_8 = Charset.forName("UTF-8");
    }
}
