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

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

import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.assetstore.AssetKeyValidator;
import java.util.function.Supplier;
import com.hypixel.hytale.codec.codecs.map.MapCodec;
import java.util.HashMap;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import javax.annotation.Nonnull;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.hypixel.hytale.server.core.prefab.selection.mask.BlockPattern;
import java.util.Optional;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.assetstore.AssetRegistry;
import java.util.Map;
import com.hypixel.hytale.assetstore.AssetExtraInfo;
import com.hypixel.hytale.assetstore.AssetStore;
import com.hypixel.hytale.codec.validation.ValidatorCache;
import com.hypixel.hytale.assetstore.codec.AssetBuilderCodec;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;

public class CustomConnectedBlockTemplateAsset implements JsonAssetWithMap<String, DefaultAssetMap<String, CustomConnectedBlockTemplateAsset>>
{
    public static final AssetBuilderCodec<String, CustomConnectedBlockTemplateAsset> CODEC;
    public static final ValidatorCache<String> VALIDATOR_CACHE;
    private static AssetStore<String, CustomConnectedBlockTemplateAsset, DefaultAssetMap<String, CustomConnectedBlockTemplateAsset>> ASSET_STORE;
    private String id;
    private AssetExtraInfo.Data data;
    protected boolean connectsToOtherMaterials;
    private boolean dontUpdateAfterInitialPlacement;
    private String defaultShapeName;
    protected Map<String, ConnectedBlockShape> connectedBlockShapes;
    
    public CustomConnectedBlockTemplateAsset() {
        this.connectsToOtherMaterials = true;
    }
    
    public static AssetStore<String, CustomConnectedBlockTemplateAsset, DefaultAssetMap<String, CustomConnectedBlockTemplateAsset>> getAssetStore() {
        if (CustomConnectedBlockTemplateAsset.ASSET_STORE == null) {
            CustomConnectedBlockTemplateAsset.ASSET_STORE = AssetRegistry.getAssetStore(CustomConnectedBlockTemplateAsset.class);
        }
        return CustomConnectedBlockTemplateAsset.ASSET_STORE;
    }
    
    public static DefaultAssetMap<String, CustomConnectedBlockTemplateAsset> getAssetMap() {
        return getAssetStore().getAssetMap();
    }
    
    @Nonnull
    public Optional<ConnectedBlocksUtil.ConnectedBlockResult> getConnectedBlockType(final World world, final Vector3i coordinate, final CustomTemplateConnectedBlockRuleSet ruleSet, final BlockType blockType, final int rotation, final Vector3i placementNormal, final boolean useDefaultShapeIfNoMatch, final boolean isPlacement) {
        for (final Map.Entry<String, ConnectedBlockShape> entry : this.connectedBlockShapes.entrySet()) {
            final ConnectedBlockShape connectedBlockShape = entry.getValue();
            if (connectedBlockShape == null) {
                continue;
            }
            final CustomTemplateConnectedBlockPattern[] patterns = connectedBlockShape.getPatternsToMatchAnyOf();
            if (patterns == null) {
                continue;
            }
            for (final CustomTemplateConnectedBlockPattern connectedBlockPattern : patterns) {
                final Optional<ConnectedBlocksUtil.ConnectedBlockResult> blockRotationIfMatchedOptional = connectedBlockPattern.getConnectedBlockTypeKey(entry.getKey(), world, coordinate, ruleSet, blockType, rotation, placementNormal, isPlacement);
                if (!blockRotationIfMatchedOptional.isEmpty()) {
                    return blockRotationIfMatchedOptional;
                }
            }
        }
        if (!useDefaultShapeIfNoMatch) {
            return Optional.empty();
        }
        final BlockPattern defaultShapeBlockPattern = ruleSet.getShapeNameToBlockPatternMap().get(this.defaultShapeName);
        if (defaultShapeBlockPattern == null) {
            return Optional.empty();
        }
        final BlockPattern.BlockEntry defaultBlock = defaultShapeBlockPattern.nextBlockTypeKey(ThreadLocalRandom.current());
        return Optional.of(new ConnectedBlocksUtil.ConnectedBlockResult(defaultBlock.blockTypeKey(), rotation));
    }
    
    public boolean isDontUpdateAfterInitialPlacement() {
        return this.dontUpdateAfterInitialPlacement;
    }
    
    @Override
    public String getId() {
        return this.id;
    }
    
    static {
        CODEC = ((AssetBuilderCodec.Builder)AssetBuilderCodec.builder(CustomConnectedBlockTemplateAsset.class, CustomConnectedBlockTemplateAsset::new, (Codec<String>)Codec.STRING, (builder, id) -> builder.id = id, builder -> builder.id, (builder, data) -> builder.data = data, builder -> builder.data).append(new KeyedCodec<Boolean>("DontUpdateAfterInitialPlacement", Codec.BOOLEAN, false), (o, dontUpdateAfterInitialPlacement) -> o.dontUpdateAfterInitialPlacement = dontUpdateAfterInitialPlacement, o -> o.dontUpdateAfterInitialPlacement).documentation("Default to false. When true, will not update the connected block after initial placement. Neighboring block updates won't affect this block when true.").add().append(new KeyedCodec("ConnectsToOtherMaterials", Codec.BOOLEAN, false), (o, connectsToOtherMaterials) -> o.connectsToOtherMaterials = connectsToOtherMaterials, o -> o.connectsToOtherMaterials).documentation("Defaults to true. If true, the material will connect to other materials of different block type sets, if false, the material will only connect to its own block types within the material").add().append(new KeyedCodec("DefaultShape", Codec.STRING, false), (o, defaultShapeName) -> o.defaultShapeName = defaultShapeName, o -> o.defaultShapeName).add().append(new KeyedCodec("Shapes", new MapCodec(ConnectedBlockShape.CODEC, HashMap::new), true), (o, connectedBlockShapes) -> o.connectedBlockShapes = connectedBlockShapes, o -> o.connectedBlockShapes).add()).build();
        VALIDATOR_CACHE = new ValidatorCache<String>(new AssetKeyValidator<String>(CustomConnectedBlockTemplateAsset::getAssetStore));
    }
}
