package net.minecraft.util;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import com.mojang.serialization.Keyable;
import java.util.Optional;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import java.util.function.IntFunction;
import java.util.function.ToIntFunction;
import com.mojang.serialization.Codec;
import java.util.function.Function;
import java.util.function.Supplier;

public interface StringRepresentable {
    String getSerializedName();
    
    default <E extends Enum> Codec<E> fromEnum(final Supplier<E[]> supplier, final Function<? super String, ? extends E> function) {
        final E[] arr3 = supplier.get();
        return StringRepresentable.<E>fromStringResolver(java.lang.Enum::ordinal, integer -> arr3[integer], function);
    }
    
    default <E extends StringRepresentable> Codec<E> fromStringResolver(final ToIntFunction<E> toIntFunction, final IntFunction<E> intFunction, final Function<? super String, ? extends E> function) {
        return (Codec<E>)new Codec<E>() {
            public <T> DataResult<T> encode(final E aeh, final DynamicOps<T> dynamicOps, final T object) {
                if (dynamicOps.compressMaps()) {
                    return (DataResult<T>)dynamicOps.mergeToPrimitive(object, dynamicOps.createInt(toIntFunction.applyAsInt(aeh)));
                }
                return (DataResult<T>)dynamicOps.mergeToPrimitive(object, dynamicOps.createString(aeh.getSerializedName()));
            }
            
            public <T> DataResult<Pair<E, T>> decode(final DynamicOps<T> dynamicOps, final T object) {
                if (dynamicOps.compressMaps()) {
                    return (DataResult<Pair<E, T>>)dynamicOps.getNumberValue(object).flatMap(number -> Optional.ofNullable(intFunction.apply(number.intValue())).map(DataResult::success).orElseGet(() -> DataResult.error("Unknown element id: " + number))).map(aeh -> Pair.of(aeh, dynamicOps.empty()));
                }
                return (DataResult<Pair<E, T>>)dynamicOps.getStringValue(object).flatMap(string -> Optional.ofNullable(function.apply(string)).map(DataResult::success).orElseGet(() -> DataResult.error("Unknown element name: " + string))).map(aeh -> Pair.of(aeh, dynamicOps.empty()));
            }
            
            @Override
            public String toString() {
                return "StringRepresentable[" + toIntFunction + "]";
            }
        };
    }
    
    default Keyable keys(final StringRepresentable[] arr) {
        return (Keyable)new Keyable() {
            public <T> Stream<T> keys(final DynamicOps<T> dynamicOps) {
                if (dynamicOps.compressMaps()) {
                    return IntStream.range(0, arr.length).<T>mapToObj(dynamicOps::createInt);
                }
                return Arrays.<StringRepresentable>stream(arr).map(StringRepresentable::getSerializedName).<T>map(dynamicOps::createString);
            }
        };
    }
}
