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

package com.hypixel.hytale.builtin.mounts.interactions;

import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.codec.validation.LateValidator;
import com.hypixel.hytale.protocol.RailPoint;
import com.hypixel.hytale.protocol.RailConfig;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.builtin.mounts.minecart.MinecartComponent;
import com.hypixel.hytale.server.core.modules.interaction.Interactions;
import com.hypixel.hytale.server.core.modules.entity.component.Interactable;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.math.vector.Vector3i;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.CommandBuffer;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.World;
import java.util.Collections;
import com.hypixel.hytale.protocol.InteractionType;
import java.util.Map;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;

public class SpawnMinecartInteraction extends SimpleBlockInteraction
{
    public static final BuilderCodec<SpawnMinecartInteraction> CODEC;
    private String modelId;
    private Map<InteractionType, String> cartInteractions;
    
    public SpawnMinecartInteraction() {
        this.cartInteractions = Collections.emptyMap();
    }
    
    @Override
    protected void interactWithBlock(@Nonnull final World world, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final InteractionType type, @Nonnull final InteractionContext context, @Nullable final ItemStack itemInHand, @Nonnull final Vector3i targetBlock, @Nonnull final CooldownHandler cooldownHandler) {
        final Ref<EntityStore> ref = context.getEntity();
        final Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
        final Vector3d targetPosition = targetBlock.toVector3d();
        targetPosition.add(0.5, 0.5, 0.5);
        final Vector3f rotation = new Vector3f();
        final HeadRotation headRotation = commandBuffer.getComponent(ref, HeadRotation.getComponentType());
        if (headRotation != null) {
            rotation.setYaw(headRotation.getRotation().getYaw());
        }
        final WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z));
        if (chunk == null) {
            return;
        }
        final BlockType block = chunk.getBlockType(targetBlock);
        final int blockRotation = chunk.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
        final RailConfig railConfig = block.getRailConfig(blockRotation);
        if (railConfig != null) {
            alignToRail(targetBlock, targetPosition, rotation, rotation.getYaw(), railConfig);
        }
        else {
            final BlockBoundingBoxes.RotatedVariantBoxes bounding = BlockBoundingBoxes.getAssetMap().getAsset(block.getHitboxTypeIndex()).get(blockRotation);
            targetPosition.add(0.0, bounding.getBoundingBox().max.y - 0.5, 0.0);
        }
        holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(targetPosition, rotation));
        holder.ensureComponent(UUIDComponent.getComponentType());
        ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(this.modelId);
        if (modelAsset == null) {
            modelAsset = ModelAsset.DEBUG;
        }
        final Model model = Model.createRandomScaleModel(modelAsset);
        holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
        holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
        holder.addComponent(BoundingBox.getComponentType(), new BoundingBox(model.getBoundingBox()));
        holder.ensureComponent(Interactable.getComponentType());
        holder.addComponent(Interactions.getComponentType(), new Interactions(this.cartInteractions));
        holder.putComponent(MinecartComponent.getComponentType(), new MinecartComponent((context.getHeldItem() != null) ? context.getHeldItem().getItemId() : null));
        commandBuffer.addEntity(holder, AddReason.SPAWN);
    }
    
    @Override
    protected void simulateInteractWithBlock(@Nonnull final InteractionType type, @Nonnull final InteractionContext context, @Nullable final ItemStack itemInHand, @Nonnull final World world, @Nonnull final Vector3i targetBlock) {
    }
    
    private static void alignToRail(@Nonnull final Vector3i targetBlock, @Nonnull final Vector3d target, @Nonnull final Vector3f rotation, final float yaw, @Nonnull final RailConfig config) {
        final RailPoint[] points = config.points;
        double smallestDistance = Double.MAX_VALUE;
        double ox = target.x;
        double oy = target.y;
        double oz = target.z;
        final Vector3d facingDir = new Vector3d();
        facingDir.assign(yaw, 0.0);
        for (int index = 0; index < points.length - 1; ++index) {
            final RailPoint p = points[index];
            final RailPoint p2 = points[index + 1];
            final Vector3d point = new Vector3d(targetBlock.x + p.point.x, targetBlock.y + p.point.y, targetBlock.z + p.point.z);
            final Vector3d point2 = new Vector3d(targetBlock.x + p2.point.x, targetBlock.y + p2.point.y, targetBlock.z + p2.point.z);
            final Vector3d dir = point2.clone().subtract(point);
            final double maxLength = dir.length();
            dir.normalize();
            final Vector3d toPoint = target.clone().subtract(point);
            final double distance = dir.dot(toPoint);
            final Vector3d pointOnLine = point.clone();
            pointOnLine.addScaled(dir, Math.min(maxLength, Math.max(0.0, distance)));
            final double pointDist = pointOnLine.distanceSquaredTo(target);
            if (pointDist >= 0.0 && pointDist <= 0.800000011920929 && pointDist < smallestDistance) {
                ox = pointOnLine.x;
                oy = pointOnLine.y;
                oz = pointOnLine.z;
                smallestDistance = pointDist;
                if (facingDir.dot(dir) < 0.0) {
                    dir.scale(-1.0);
                }
                final float newYaw = (float)(Math.atan2(dir.x, dir.z) + 3.141592653589793);
                final float newPitch = (float)Math.asin(dir.y);
                rotation.setYaw(newYaw);
                rotation.setPitch(newPitch);
            }
        }
        if (smallestDistance >= Double.MAX_VALUE) {
            return;
        }
        target.assign(ox, oy, oz);
    }
    
    static {
        // 
        // This method could not be decompiled.
        // 
        // Original Bytecode:
        // 
        //     2: invokedynamic   BootstrapMethod #0, get:()Ljava/util/function/Supplier;
        //     7: getstatic       com/hypixel/hytale/server/core/modules/interaction/interaction/config/client/SimpleBlockInteraction.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //    10: invokestatic    com/hypixel/hytale/codec/builder/BuilderCodec.builder:(Ljava/lang/Class;Ljava/util/function/Supplier;Lcom/hypixel/hytale/codec/builder/BuilderCodec;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    13: ldc_w           "Spawns a minecart at the target block"
        //    16: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.documentation:(Ljava/lang/String;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //    19: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    22: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    25: dup            
        //    26: ldc_w           "Model"
        //    29: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
        //    32: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    35: invokedynamic   BootstrapMethod #1, accept:()Ljava/util/function/BiConsumer;
        //    40: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/Function;
        //    45: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
        //    50: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.appendInherited:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;Ljava/util/function/BiConsumer;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    53: getstatic       com/hypixel/hytale/server/core/asset/type/model/config/ModelAsset.VALIDATOR_CACHE:Lcom/hypixel/hytale/codec/validation/ValidatorCache;
        //    56: invokevirtual   com/hypixel/hytale/codec/validation/ValidatorCache.getValidator:()Lcom/hypixel/hytale/codec/validation/Validator;
        //    59: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.addValidator:(Lcom/hypixel/hytale/codec/validation/Validator;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    62: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //    65: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    68: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    71: dup            
        //    72: ldc_w           "CartInteractions"
        //    75: new             Lcom/hypixel/hytale/codec/codecs/map/EnumMapCodec;
        //    78: dup            
        //    79: ldc_w           Lcom/hypixel/hytale/protocol/InteractionType;.class
        //    82: getstatic       com/hypixel/hytale/server/core/modules/interaction/interaction/config/RootInteraction.CHILD_ASSET_CODEC:Lcom/hypixel/hytale/assetstore/codec/ContainedAssetCodec;
        //    85: invokespecial   com/hypixel/hytale/codec/codecs/map/EnumMapCodec.<init>:(Ljava/lang/Class;Lcom/hypixel/hytale/codec/Codec;)V
        //    88: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    91: invokedynamic   BootstrapMethod #4, accept:()Ljava/util/function/BiConsumer;
        //    96: invokedynamic   BootstrapMethod #5, apply:()Ljava/util/function/Function;
        //   101: invokedynamic   BootstrapMethod #6, accept:()Ljava/util/function/BiConsumer;
        //   106: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.appendInherited:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;Ljava/util/function/BiConsumer;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   109: invokedynamic   BootstrapMethod #7, get:()Ljava/util/function/Supplier;
        //   114: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.addValidatorLate:(Ljava/util/function/Supplier;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   117: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   120: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   123: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   126: putstatic       com/hypixel/hytale/builtin/mounts/interactions/SpawnMinecartInteraction.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   129: return         
        // 
        // The error that occurred was:
        // 
        // java.lang.UnsupportedOperationException: The requested operation is not supported.
        //     at com.strobel.util.ContractUtils.unsupported(ContractUtils.java:27)
        //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:284)
        //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:279)
        //     at com.strobel.assembler.metadata.TypeReference.makeGenericType(TypeReference.java:154)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:225)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
        //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:211)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
        //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:314)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2611)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1083)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:684)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:667)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:373)
        //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:344)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:42)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:206)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
        //     at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
        //     at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
        //     at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:129)
        // 
        throw new IllegalStateException("An error occurred while decompiling this method.");
    }
}
