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

package com.hypixel.hytale.server.worldgen.util.condition;

import com.hypixel.hytale.server.worldgen.util.ResolvedBlockArray;
import java.util.Arrays;
import java.util.Objects;
import javax.annotation.Nullable;
import com.hypixel.hytale.math.util.MathUtil;
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import javax.annotation.Nonnull;

public class BlockMaskCondition
{
    public static final Mask DEFAULT_MASK;
    public static final BlockMaskCondition DEFAULT_TRUE;
    public static final BlockMaskCondition DEFAULT_FALSE;
    @Nonnull
    private Mask defaultMask;
    @Nonnull
    private Long2ObjectMap<Mask> specificMasks;
    
    public BlockMaskCondition() {
        this.defaultMask = BlockMaskCondition.DEFAULT_MASK;
        this.specificMasks = Long2ObjectMaps.emptyMap();
    }
    
    public void set(@Nonnull final Mask defaultMask, @Nonnull final Long2ObjectMap<Mask> specificMasks) {
        this.defaultMask = defaultMask;
        this.specificMasks = specificMasks;
    }
    
    public boolean eval(final int currentBlock, final int currentFluid, final int nextBlockId, final int nextFluidId) {
        final Mask mask = this.specificMasks.getOrDefault(MathUtil.packLong(nextBlockId, nextFluidId), this.defaultMask);
        return mask.shouldReplace(currentBlock, currentFluid);
    }
    
    @Override
    public boolean equals(@Nullable final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final BlockMaskCondition that = (BlockMaskCondition)o;
        return this.defaultMask.equals(that.defaultMask) && Objects.equals(this.specificMasks, that.specificMasks);
    }
    
    @Override
    public int hashCode() {
        int result = this.defaultMask.hashCode();
        result = 31 * result + ((this.specificMasks != null) ? this.specificMasks.hashCode() : 0);
        return result;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "BlockMaskCondition{defaultMask=" + String.valueOf(this.defaultMask) + ", specificMasks=" + String.valueOf(this.specificMasks);
    }
    
    static {
        DEFAULT_MASK = new Mask(true, new MaskEntry[0]);
        DEFAULT_TRUE = new BlockMaskCondition();
        DEFAULT_FALSE = new BlockMaskCondition();
    }
    
    public static class Mask
    {
        private final boolean matchEmpty;
        private final MaskEntry[] entries;
        
        public Mask(@Nonnull final MaskEntry[] entries) {
            this(false, entries);
        }
        
        private Mask(final boolean matchEmpty, @Nonnull final MaskEntry[] entries) {
            this.entries = entries;
            this.matchEmpty = matchEmpty;
        }
        
        public boolean shouldReplace(final int current, final int fluid) {
            for (final MaskEntry entry : this.entries) {
                if (entry.shouldHandle(current, fluid)) {
                    return entry.shouldReplace();
                }
            }
            return this.matchEmpty && (current == 0 || fluid == 0);
        }
        
        @Override
        public boolean equals(@Nullable final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || this.getClass() != o.getClass()) {
                return false;
            }
            final Mask mask = (Mask)o;
            return Arrays.equals(this.entries, mask.entries);
        }
        
        @Override
        public int hashCode() {
            return Arrays.hashCode(this.entries);
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "Mask{entries=" + Arrays.toString(this.entries);
        }
    }
    
    public static class MaskEntry
    {
        public static final MaskEntry WILDCARD_TRUE;
        public static final MaskEntry WILDCARD_FALSE;
        private ResolvedBlockArray blocks;
        private final boolean any;
        private boolean replace;
        
        public MaskEntry() {
            this(false, false);
        }
        
        private MaskEntry(final boolean any, final boolean replace) {
            this.blocks = ResolvedBlockArray.EMPTY;
            this.any = any;
            this.replace = replace;
        }
        
        public void set(final ResolvedBlockArray blocks, final boolean replace) {
            this.blocks = blocks;
            this.replace = replace;
        }
        
        public boolean shouldHandle(final int current, final int fluid) {
            return this.any || this.blocks.contains(current, fluid);
        }
        
        public boolean shouldReplace() {
            return this.replace;
        }
        
        @Override
        public boolean equals(@Nullable final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || this.getClass() != o.getClass()) {
                return false;
            }
            final MaskEntry that = (MaskEntry)o;
            return this.any == that.any && this.replace == that.replace && this.blocks.equals(that.blocks);
        }
        
        @Override
        public int hashCode() {
            int result = this.blocks.hashCode();
            result = 31 * result + (this.any ? 1 : 0);
            result = 31 * result + (this.replace ? 1 : 0);
            return result;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "MaskEntry{blocks=" + String.valueOf(this.blocks) + ", replace=" + this.replace;
        }
        
        static {
            WILDCARD_TRUE = new MaskEntry(true, true);
            WILDCARD_FALSE = new MaskEntry(true, false);
        }
    }
}
