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

package com.hypixel.hytale.builtin.adventure.farming.config.modifiers;

import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.time.Instant;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.builtin.weather.resources.WeatherResource;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
import javax.annotation.Nullable;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
import com.hypixel.hytale.builtin.adventure.farming.states.TilledSoilBlock;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.component.CommandBuffer;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.farming.GrowthModifierAsset;

public class WaterGrowthModifierAsset extends GrowthModifierAsset
{
    public static final BuilderCodec<WaterGrowthModifierAsset> CODEC;
    protected String[] fluids;
    protected IntOpenHashSet fluidIds;
    protected String[] weathers;
    protected IntOpenHashSet weatherIds;
    protected int rainDuration;
    
    public String[] getFluids() {
        return this.fluids;
    }
    
    public IntOpenHashSet getFluidIds() {
        return this.fluidIds;
    }
    
    public String[] getWeathers() {
        return this.weathers;
    }
    
    public IntOpenHashSet getWeatherIds() {
        return this.weatherIds;
    }
    
    public int getRainDuration() {
        return this.rainDuration;
    }
    
    @Override
    public double getCurrentGrowthMultiplier(final CommandBuffer<ChunkStore> commandBuffer, final Ref<ChunkStore> sectionRef, final Ref<ChunkStore> blockRef, final int x, final int y, final int z, final boolean initialTick) {
        final boolean hasWaterBlock = this.checkIfWaterSource(commandBuffer, sectionRef, blockRef, x, y, z);
        final boolean isRaining = this.checkIfRaining(commandBuffer, sectionRef, x, y, z);
        boolean active = hasWaterBlock || isRaining;
        final TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z);
        if (soil != null) {
            if (soil.hasExternalWater() != active) {
                soil.setExternalWater(active);
                commandBuffer.getComponent(sectionRef, BlockSection.getComponentType()).setTicking(x, y, z, true);
            }
            active |= this.isSoilWaterExpiring(commandBuffer.getExternalData().getWorld().getEntityStore().getStore().getResource(WorldTimeResource.getResourceType()), soil);
        }
        if (!active) {
            return 1.0;
        }
        return super.getCurrentGrowthMultiplier(commandBuffer, sectionRef, blockRef, x, y, z, initialTick);
    }
    
    @Nullable
    private static TilledSoilBlock getSoil(final CommandBuffer<ChunkStore> commandBuffer, final Ref<ChunkStore> sectionRef, final int x, final int y, final int z) {
        final ChunkSection chunkSection = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
        final Ref<ChunkStore> chunk = chunkSection.getChunkColumnReference();
        final BlockComponentChunk blockComponentChunk = commandBuffer.getComponent(chunk, BlockComponentChunk.getComponentType());
        final Ref<ChunkStore> blockRefBelow = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(x, y - 1, z));
        if (blockRefBelow == null) {
            return null;
        }
        return commandBuffer.getComponent(blockRefBelow, TilledSoilBlock.getComponentType());
    }
    
    protected boolean checkIfWaterSource(final CommandBuffer<ChunkStore> commandBuffer, final Ref<ChunkStore> sectionRef, final Ref<ChunkStore> blockRef, final int x, final int y, final int z) {
        final IntOpenHashSet waterBlocks = this.fluidIds;
        if (waterBlocks == null) {
            return false;
        }
        final TilledSoilBlock soil = getSoil(commandBuffer, sectionRef, x, y, z);
        if (soil == null) {
            return false;
        }
        final int[] neighbourFluids;
        final int[] fluids = neighbourFluids = this.getNeighbourFluids(commandBuffer, sectionRef, x, y - 1, z);
        for (final int block : neighbourFluids) {
            if (waterBlocks.contains(block)) {
                return true;
            }
        }
        return false;
    }
    
    private int[] getNeighbourFluids(final CommandBuffer<ChunkStore> commandBuffer, final Ref<ChunkStore> sectionRef, final int x, final int y, final int z) {
        final ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
        return new int[] { this.getFluidAtPos(x - 1, y, z, sectionRef, section, commandBuffer), this.getFluidAtPos(x + 1, y, z, sectionRef, section, commandBuffer), this.getFluidAtPos(x, y, z - 1, sectionRef, section, commandBuffer), this.getFluidAtPos(x, y, z + 1, sectionRef, section, commandBuffer) };
    }
    
    private int getFluidAtPos(final int posX, final int posY, final int posZ, final Ref<ChunkStore> sectionRef, final ChunkSection currentChunkSection, final CommandBuffer<ChunkStore> commandBuffer) {
        Ref<ChunkStore> chunkToUse = sectionRef;
        final int chunkX = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getX(), posX);
        final int chunkY = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getY(), posY);
        final int chunkZ = ChunkUtil.worldCoordFromLocalCoord(currentChunkSection.getZ(), posZ);
        if (ChunkUtil.isSameChunkSection(chunkX, chunkY, chunkZ, currentChunkSection.getX(), currentChunkSection.getY(), currentChunkSection.getZ())) {
            chunkToUse = commandBuffer.getExternalData().getChunkSectionReference(chunkX, chunkY, chunkZ);
        }
        if (chunkToUse == null) {
            return Integer.MIN_VALUE;
        }
        return commandBuffer.getComponent(chunkToUse, FluidSection.getComponentType()).getFluidId(posX, posY, posZ);
    }
    
    protected boolean checkIfRaining(final CommandBuffer<ChunkStore> commandBuffer, final Ref<ChunkStore> sectionRef, final int x, final int y, final int z) {
        if (this.weatherIds == null) {
            return false;
        }
        final ChunkSection section = commandBuffer.getComponent(sectionRef, ChunkSection.getComponentType());
        final Ref<ChunkStore> chunk = section.getChunkColumnReference();
        final BlockChunk blockChunk = commandBuffer.getComponent(chunk, BlockChunk.getComponentType());
        final int cropId = blockChunk.getBlock(x, y, z);
        final Store<EntityStore> store = commandBuffer.getExternalData().getWorld().getEntityStore().getStore();
        final WorldTimeResource worldTimeResource = store.getResource(WorldTimeResource.getResourceType());
        final WeatherResource weatherResource = store.getResource(WeatherResource.getResourceType());
        final int environment = blockChunk.getEnvironment(x, y, z);
        int weatherId;
        if (weatherResource.getForcedWeatherIndex() != 0) {
            weatherId = weatherResource.getForcedWeatherIndex();
        }
        else {
            weatherId = weatherResource.getWeatherIndexForEnvironment(environment);
        }
        if (this.weatherIds.contains(weatherId)) {
            boolean unobstructed = true;
            for (int searchY = y + 1; searchY < 320; ++searchY) {
                final int block = blockChunk.getBlock(x, searchY, z);
                if (block != 0 && block != cropId) {
                    unobstructed = false;
                    break;
                }
            }
            if (unobstructed) {
                return true;
            }
        }
        return false;
    }
    
    private boolean isSoilWaterExpiring(final WorldTimeResource worldTimeResource, final TilledSoilBlock soilBlock) {
        final Instant until = soilBlock.getWateredUntil();
        if (until == null) {
            return false;
        }
        final Instant now = worldTimeResource.getGameTime();
        if (now.isAfter(until)) {
            soilBlock.setWateredUntil(null);
            return false;
        }
        return true;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "WaterGrowthModifierAsset{blocks=" + Arrays.toString(this.fluids) + ", blockIds=" + String.valueOf(this.fluidIds) + ", weathers=" + Arrays.toString(this.weathers) + ", weatherIds=" + String.valueOf(this.weatherIds) + ", rainDuration=" + this.rainDuration + "} " + super.toString();
    }
    
    static {
        // 
        // This method could not be decompiled.
        // 
        // Original Bytecode:
        // 
        //     2: invokedynamic   BootstrapMethod #1, get:()Ljava/util/function/Supplier;
        //     7: getstatic       com/hypixel/hytale/builtin/adventure/farming/config/modifiers/WaterGrowthModifierAsset.ABSTRACT_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: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    16: dup            
        //    17: ldc_w           "Fluids"
        //    20: new             Lcom/hypixel/hytale/codec/codecs/array/ArrayCodec;
        //    23: dup            
        //    24: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
        //    27: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/IntFunction;
        //    32: invokespecial   com/hypixel/hytale/codec/codecs/array/ArrayCodec.<init>:(Lcom/hypixel/hytale/codec/Codec;Ljava/util/function/IntFunction;)V
        //    35: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    38: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
        //    43: invokedynamic   BootstrapMethod #4, apply:()Ljava/util/function/Function;
        //    48: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    51: getstatic       com/hypixel/hytale/server/core/asset/type/fluid/Fluid.VALIDATOR_CACHE:Lcom/hypixel/hytale/codec/validation/ValidatorCache;
        //    54: invokevirtual   com/hypixel/hytale/codec/validation/ValidatorCache.getArrayValidator:()Lcom/hypixel/hytale/codec/validation/validator/ArrayValidator;
        //    57: invokevirtual   com/hypixel/hytale/codec/validation/validator/ArrayValidator.late:()Lcom/hypixel/hytale/codec/validation/LateValidator;
        //    60: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.addValidator:(Lcom/hypixel/hytale/codec/validation/Validator;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    63: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //    66: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    69: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    72: dup            
        //    73: ldc_w           "Weathers"
        //    76: getstatic       com/hypixel/hytale/codec/Codec.STRING_ARRAY:Lcom/hypixel/hytale/codec/codecs/array/ArrayCodec;
        //    79: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    82: invokedynamic   BootstrapMethod #5, accept:()Ljava/util/function/BiConsumer;
        //    87: invokedynamic   BootstrapMethod #6, apply:()Ljava/util/function/Function;
        //    92: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    95: getstatic       com/hypixel/hytale/server/core/asset/type/weather/config/Weather.VALIDATOR_CACHE:Lcom/hypixel/hytale/codec/validation/ValidatorCache;
        //    98: invokevirtual   com/hypixel/hytale/codec/validation/ValidatorCache.getArrayValidator:()Lcom/hypixel/hytale/codec/validation/validator/ArrayValidator;
        //   101: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.addValidator:(Lcom/hypixel/hytale/codec/validation/Validator;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   104: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   107: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   110: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //   113: dup            
        //   114: ldc_w           "RainDuration"
        //   117: getstatic       com/hypixel/hytale/codec/Codec.INTEGER:Lcom/hypixel/hytale/codec/codecs/simple/IntegerCodec;
        //   120: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //   123: invokedynamic   BootstrapMethod #7, accept:()Ljava/util/function/BiConsumer;
        //   128: invokedynamic   BootstrapMethod #8, apply:()Ljava/util/function/Function;
        //   133: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.addField:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   136: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   139: invokedynamic   BootstrapMethod #9, accept:()Ljava/util/function/Consumer;
        //   144: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.afterDecode:(Ljava/util/function/Consumer;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   147: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   150: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   153: putstatic       com/hypixel/hytale/builtin/adventure/farming/config/modifiers/WaterGrowthModifierAsset.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   156: 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.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: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: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.inferTypesForVariables(TypeAnalysis.java:593)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:405)
        //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:109)
        //     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.");
    }
}
