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

package org.bson.codecs;

import java.util.UUID;
import java.util.Iterator;
import org.bson.BsonWriter;
import java.util.List;
import org.bson.BsonType;
import java.util.ArrayList;
import org.bson.BsonReader;
import org.bson.assertions.Assertions;
import org.bson.UuidRepresentation;
import org.bson.Transformer;
import org.bson.codecs.configuration.CodecRegistry;

public class IterableCodec implements Codec<Iterable>, OverridableUuidRepresentationCodec<Iterable>
{
    private final CodecRegistry registry;
    private final BsonTypeCodecMap bsonTypeCodecMap;
    private final Transformer valueTransformer;
    private final UuidRepresentation uuidRepresentation;
    
    public IterableCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTypeClassMap) {
        this(registry, bsonTypeClassMap, null);
    }
    
    public IterableCodec(final CodecRegistry registry, final BsonTypeClassMap bsonTypeClassMap, final Transformer valueTransformer) {
        this(registry, new BsonTypeCodecMap(Assertions.notNull("bsonTypeClassMap", bsonTypeClassMap), registry), valueTransformer, UuidRepresentation.UNSPECIFIED);
    }
    
    private IterableCodec(final CodecRegistry registry, final BsonTypeCodecMap bsonTypeCodecMap, final Transformer valueTransformer, final UuidRepresentation uuidRepresentation) {
        this.registry = Assertions.notNull("registry", registry);
        this.bsonTypeCodecMap = bsonTypeCodecMap;
        this.valueTransformer = ((valueTransformer != null) ? valueTransformer : new Transformer() {
            @Override
            public Object transform(final Object objectToTransform) {
                return objectToTransform;
            }
        });
        this.uuidRepresentation = uuidRepresentation;
    }
    
    @Override
    public Codec<Iterable> withUuidRepresentation(final UuidRepresentation uuidRepresentation) {
        return new IterableCodec(this.registry, this.bsonTypeCodecMap, this.valueTransformer, uuidRepresentation);
    }
    
    @Override
    public Iterable decode(final BsonReader reader, final DecoderContext decoderContext) {
        reader.readStartArray();
        final List<Object> list = new ArrayList<Object>();
        while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
            list.add(this.readValue(reader, decoderContext));
        }
        reader.readEndArray();
        return list;
    }
    
    @Override
    public void encode(final BsonWriter writer, final Iterable value, final EncoderContext encoderContext) {
        writer.writeStartArray();
        for (final Object cur : value) {
            this.writeValue(writer, encoderContext, cur);
        }
        writer.writeEndArray();
    }
    
    @Override
    public Class<Iterable> getEncoderClass() {
        return Iterable.class;
    }
    
    private void writeValue(final BsonWriter writer, final EncoderContext encoderContext, final Object value) {
        if (value == null) {
            writer.writeNull();
        }
        else {
            final Codec codec = this.registry.get(value.getClass());
            encoderContext.encodeWithChildContext(codec, writer, value);
        }
    }
    
    private Object readValue(final BsonReader reader, final DecoderContext decoderContext) {
        final BsonType bsonType = reader.getCurrentBsonType();
        if (bsonType == BsonType.NULL) {
            reader.readNull();
            return null;
        }
        Codec<?> codec = this.bsonTypeCodecMap.get(bsonType);
        if (bsonType == BsonType.BINARY && reader.peekBinarySize() == 16) {
            switch (reader.peekBinarySubType()) {
                case 3: {
                    if (this.uuidRepresentation == UuidRepresentation.JAVA_LEGACY || this.uuidRepresentation == UuidRepresentation.C_SHARP_LEGACY || this.uuidRepresentation == UuidRepresentation.PYTHON_LEGACY) {
                        codec = this.registry.get((Class<?>)UUID.class);
                        break;
                    }
                    break;
                }
                case 4: {
                    if (this.uuidRepresentation == UuidRepresentation.STANDARD) {
                        codec = this.registry.get((Class<?>)UUID.class);
                        break;
                    }
                    break;
                }
            }
        }
        return this.valueTransformer.transform(codec.decode(reader, decoderContext));
    }
}
