package net.minecraft.world.level.storage.loot.functions;

import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.util.GsonHelper;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonArray;
import net.minecraft.core.Registry;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import com.google.common.collect.Sets;
import java.util.function.Predicate;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParam;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Set;
import net.minecraft.world.level.block.Block;

public class CopyBlockState extends LootItemConditionalFunction {
    private final Block block;
    private final Set<Property<?>> properties;
    
    private CopyBlockState(final LootItemCondition[] arr, final Block bph, final Set<Property<?>> set) {
        super(arr);
        this.block = bph;
        this.properties = set;
    }
    
    @Override
    public Set<LootContextParam<?>> getReferencedContextParams() {
        return ImmutableSet.of(LootContextParams.BLOCK_STATE);
    }
    
    @Override
    protected ItemStack run(final ItemStack ben, final LootContext crx) {
        final BlockState byj4 = crx.<BlockState>getParamOrNull(LootContextParams.BLOCK_STATE);
        if (byj4 != null) {
            final CompoundTag jt5 = ben.getOrCreateTag();
            CompoundTag jt6;
            if (jt5.contains("BlockStateTag", 10)) {
                jt6 = jt5.getCompound("BlockStateTag");
            }
            else {
                jt6 = new CompoundTag();
                jt5.put("BlockStateTag", jt6);
            }
            this.properties.stream().filter(byj4::hasProperty).forEach(bzm -> jt6.putString(bzm.getName(), CopyBlockState.<Comparable>serialize(byj4, bzm)));
        }
        return ben;
    }
    
    public static Builder copyState(final Block bph) {
        return new Builder(bph);
    }
    
    private static <T extends Comparable<T>> String serialize(final BlockState byj, final Property<T> bzm) {
        final T comparable3 = byj.<T>getValue(bzm);
        return bzm.getName(comparable3);
    }
    
    public static class Builder extends LootItemConditionalFunction.Builder<Builder> {
        private final Block block;
        private final Set<Property<?>> properties;
        
        private Builder(final Block bph) {
            this.properties = Sets.newHashSet();
            this.block = bph;
        }
        
        public Builder copy(final Property<?> bzm) {
            if (!this.block.getStateDefinition().getProperties().contains(bzm)) {
                throw new IllegalStateException("Property " + bzm + " is not present on block " + this.block);
            }
            this.properties.add(bzm);
            return this;
        }
        
        @Override
        protected Builder getThis() {
            return this;
        }
        
        @Override
        public LootItemFunction build() {
            return new CopyBlockState(this.getConditions(), this.block, this.properties, null);
        }
    }
    
    public static class Serializer extends LootItemConditionalFunction.Serializer<CopyBlockState> {
        public Serializer() {
            super(new ResourceLocation("copy_state"), CopyBlockState.class);
        }
        
        @Override
        public void serialize(final JsonObject jsonObject, final CopyBlockState csy, final JsonSerializationContext jsonSerializationContext) {
            super.serialize(jsonObject, csy, jsonSerializationContext);
            jsonObject.addProperty("block", Registry.BLOCK.getKey(csy.block).toString());
            final JsonArray jsonArray5 = new JsonArray();
            csy.properties.forEach(bzm -> jsonArray5.add(bzm.getName()));
            jsonObject.add("properties", jsonArray5);
        }
        
        @Override
        public CopyBlockState deserialize(final JsonObject jsonObject, final JsonDeserializationContext jsonDeserializationContext, final LootItemCondition[] arr) {
            final ResourceLocation sm5 = new ResourceLocation(GsonHelper.getAsString(jsonObject, "block"));
            final Object o;
            final Object obj;
            final Block bph6 = Registry.BLOCK.getOptional(sm5).<Throwable>orElseThrow(() -> {
                new IllegalArgumentException("Can't find block " + obj);
                return o;
            });
            final StateDefinition<Block, BlockState> byk7 = bph6.getStateDefinition();
            final Set<Property<?>> set8 = Sets.newHashSet();
            final JsonArray jsonArray9 = GsonHelper.getAsJsonArray(jsonObject, "properties", null);
            if (jsonArray9 != null) {
                jsonArray9.forEach(jsonElement -> set8.add(byk7.getProperty(GsonHelper.convertToString(jsonElement, "property"))));
            }
            return new CopyBlockState(arr, bph6, set8, null);
        }
    }
}
