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

package com.hypixel.hytale.codec.codecs.map;

import com.hypixel.hytale.codec.schema.SchemaConvertable;
import com.hypixel.hytale.codec.schema.config.StringSchema;
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.codec.schema.SchemaContext;
import java.io.IOException;
import com.hypixel.hytale.codec.util.RawJsonReader;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import java.util.Iterator;
import org.bson.BsonDocument;
import it.unimi.dsi.fastutil.floats.Float2ObjectMaps;
import com.hypixel.hytale.codec.exception.CodecException;
import java.util.Map;
import com.hypixel.hytale.codec.ExtraInfo;
import javax.annotation.Nonnull;
import org.bson.BsonValue;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import com.hypixel.hytale.codec.WrappedCodec;
import it.unimi.dsi.fastutil.floats.Float2ObjectMap;
import com.hypixel.hytale.codec.Codec;

public class Float2ObjectMapCodec<T> implements Codec<Float2ObjectMap<T>>, WrappedCodec<T>
{
    public static final Pattern FLOAT_PATTERN;
    private final Codec<T> valueCodec;
    private final Supplier<Float2ObjectMap<T>> supplier;
    private final boolean unmodifiable;
    
    public Float2ObjectMapCodec(final Codec<T> valueCodec, final Supplier<Float2ObjectMap<T>> supplier, final boolean unmodifiable) {
        this.valueCodec = valueCodec;
        this.supplier = supplier;
        this.unmodifiable = unmodifiable;
    }
    
    public Float2ObjectMapCodec(final Codec<T> valueCodec, final Supplier<Float2ObjectMap<T>> supplier) {
        this(valueCodec, supplier, true);
    }
    
    @Override
    public Codec<T> getChildCodec() {
        return this.valueCodec;
    }
    
    @Override
    public Float2ObjectMap<T> decode(@Nonnull final BsonValue bsonValue, @Nonnull final ExtraInfo extraInfo) {
        final BsonDocument bsonDocument = bsonValue.asDocument();
        Float2ObjectMap<T> map = this.supplier.get();
        for (final Map.Entry<String, BsonValue> entry : bsonDocument.entrySet()) {
            final String key = entry.getKey();
            final BsonValue value = entry.getValue();
            extraInfo.pushKey(key);
            try {
                final float decodedKey = Float.parseFloat(key);
                map.put(decodedKey, this.valueCodec.decode(value, extraInfo));
            }
            catch (final Exception e) {
                throw new CodecException("Failed to decode", value, extraInfo, e);
            }
            finally {
                extraInfo.popKey();
            }
        }
        if (this.unmodifiable) {
            map = Float2ObjectMaps.unmodifiable((Float2ObjectMap<? extends T>)map);
        }
        return map;
    }
    
    @Nonnull
    @Override
    public BsonValue encode(@Nonnull final Float2ObjectMap<T> map, final ExtraInfo extraInfo) {
        final BsonDocument bsonDocument = new BsonDocument();
        for (final Float2ObjectMap.Entry<T> entry : map.float2ObjectEntrySet()) {
            bsonDocument.put(Float.toString(entry.getFloatKey()), this.valueCodec.encode(entry.getValue(), extraInfo));
        }
        return bsonDocument;
    }
    
    @Override
    public Float2ObjectMap<T> decodeJson(@Nonnull final RawJsonReader reader, @Nonnull final ExtraInfo extraInfo) throws IOException {
        reader.expect('{');
        reader.consumeWhiteSpace();
        Float2ObjectMap<T> map = this.supplier.get();
        if (reader.tryConsume('}')) {
            if (this.unmodifiable) {
                map = Float2ObjectMaps.unmodifiable((Float2ObjectMap<? extends T>)map);
            }
            return map;
        }
        while (true) {
            final String key = reader.readString();
            reader.consumeWhiteSpace();
            reader.expect(':');
            reader.consumeWhiteSpace();
            extraInfo.pushKey(key, reader);
            try {
                final float decodedKey = Float.parseFloat(key);
                map.put(decodedKey, this.valueCodec.decodeJson(reader, extraInfo));
            }
            catch (final Exception e) {
                throw new CodecException("Failed to decode", reader, extraInfo, e);
            }
            finally {
                extraInfo.popKey();
            }
            reader.consumeWhiteSpace();
            if (reader.tryConsumeOrExpect('}', ',')) {
                break;
            }
            reader.consumeWhiteSpace();
        }
        if (this.unmodifiable) {
            map = Float2ObjectMaps.unmodifiable((Float2ObjectMap<? extends T>)map);
        }
        return map;
    }
    
    @Nonnull
    @Override
    public Schema toSchema(@Nonnull final SchemaContext context) {
        final ObjectSchema s = new ObjectSchema();
        final StringSchema name = new StringSchema();
        name.setPattern(Float2ObjectMapCodec.FLOAT_PATTERN);
        name.setMarkdownDescription("A string that contains any floating point number");
        s.setPropertyNames(name);
        s.setAdditionalProperties(context.refDefinition(this.valueCodec));
        return s;
    }
    
    static {
        FLOAT_PATTERN = Pattern.compile("^[-+]?[0-9]+(.[0-9]+)?$");
    }
}
