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

package com.hypixel.hytale.server.core.universe.world.connectedblocks;

import java.util.function.Supplier;
import com.hypixel.hytale.codec.codecs.map.MapCodec;
import java.util.HashMap;
import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.Codec;
import java.util.Optional;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import javax.annotation.Nullable;
import java.util.Iterator;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Set;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern;
import java.util.Map;
import com.hypixel.hytale.codec.builder.BuilderCodec;

public class CustomTemplateConnectedBlockRuleSet extends ConnectedBlockRuleSet
{
    public static final BuilderCodec<CustomTemplateConnectedBlockRuleSet> CODEC;
    private String shapeAssetId;
    private Map<String, BlockPattern> shapeNameToBlockPatternMap;
    private final Int2ObjectMap<Set<String>> shapesPerBlockType;
    
    public CustomTemplateConnectedBlockRuleSet() {
        this.shapeNameToBlockPatternMap = new Object2ObjectOpenHashMap<String, BlockPattern>();
        this.shapesPerBlockType = new Int2ObjectOpenHashMap<Set<String>>();
    }
    
    public Map<String, BlockPattern> getShapeNameToBlockPatternMap() {
        return this.shapeNameToBlockPatternMap;
    }
    
    @Override
    public void updateCachedBlockTypes(final BlockType blockType, final BlockTypeAssetMap<String, BlockType> assetMap) {
        super.updateCachedBlockTypes(blockType, assetMap);
        for (final Map.Entry<String, BlockPattern> entry : this.shapeNameToBlockPatternMap.entrySet()) {
            final String name = entry.getKey();
            final BlockPattern blockPattern = entry.getValue();
            for (final int resolvedKey : blockPattern.getResolvedKeys()) {
                final Set<String> shapes = this.shapesPerBlockType.computeIfAbsent(resolvedKey, k -> new ObjectOpenHashSet());
                shapes.add(name);
            }
        }
    }
    
    @Nullable
    public Set<String> getShapesForBlockType(final int blockTypeKey) {
        return this.shapesPerBlockType.getOrDefault(blockTypeKey, Set.of());
    }
    
    @Nullable
    public CustomConnectedBlockTemplateAsset getShapeTemplateAsset() {
        return CustomConnectedBlockTemplateAsset.getAssetMap().getAsset(this.shapeAssetId);
    }
    
    @Override
    public boolean onlyUpdateOnPlacement() {
        final CustomConnectedBlockTemplateAsset templateAsset = this.getShapeTemplateAsset();
        return templateAsset != null && templateAsset.isDontUpdateAfterInitialPlacement();
    }
    
    @Override
    public Optional<ConnectedBlocksUtil.ConnectedBlockResult> getConnectedBlockType(final World world, final Vector3i testedCoordinate, final BlockType blockType, final int rotation, final Vector3i placementNormal, final boolean isPlacement) {
        final CustomConnectedBlockTemplateAsset shapeTemplateAsset = this.getShapeTemplateAsset();
        if (shapeTemplateAsset == null) {
            return Optional.empty();
        }
        return shapeTemplateAsset.getConnectedBlockType(world, testedCoordinate, this, blockType, rotation, placementNormal, true, isPlacement);
    }
    
    static {
        CODEC = BuilderCodec.builder(CustomTemplateConnectedBlockRuleSet.class, CustomTemplateConnectedBlockRuleSet::new).append(new KeyedCodec<String>("TemplateShapeAssetId", Codec.STRING), (ruleSet, shapeAssetId) -> ruleSet.shapeAssetId = shapeAssetId, ruleSet -> ruleSet.shapeAssetId).addValidator(CustomConnectedBlockTemplateAsset.VALIDATOR_CACHE.getValidator()).documentation("The name of a ConnectedBlockTemplateAsset asset").add().append(new KeyedCodec("TemplateShapeBlockPatterns", new MapCodec(BlockPattern.CODEC, HashMap::new), true), (material, shapeNameToBlockPatternMap) -> material.shapeNameToBlockPatternMap = shapeNameToBlockPatternMap, material -> material.shapeNameToBlockPatternMap).documentation("You must specify all shapes as a BlockPattern. The shapes are as outlined in the keys of the ShapeTemplateAsset's map.").add().build();
    }
}
