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

package com.hypixel.hytale.server.spawning.util;

import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.universe.world.World;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.spawning.assets.spawns.LightType;
import com.hypixel.hytale.math.util.MathUtil;

public class LightRangePredicate
{
    private byte lightValueMin;
    private byte lightValueMax;
    private byte skyLightValueMin;
    private byte skyLightValueMax;
    private byte sunlightValueMin;
    private byte sunlightValueMax;
    private byte redLightValueMin;
    private byte redLightValueMax;
    private byte greenLightValueMin;
    private byte greenLightValueMax;
    private byte blueLightValueMin;
    private byte blueLightValueMax;
    private boolean testLightValue;
    private boolean testSkyLightValue;
    private boolean testSunlightValue;
    private boolean testRedLightValue;
    private boolean testGreenLightValue;
    private boolean testBlueLightValue;
    
    public static int lightToPrecentage(final byte light) {
        return MathUtil.fastRound(light * 100.0f / 15.0f);
    }
    
    public void setLightRange(@Nonnull final LightType type, final double[] lightRange) {
        switch (type) {
            case Light: {
                this.setLightRange(lightRange);
                break;
            }
            case SkyLight: {
                this.setSkyLightRange(lightRange);
                break;
            }
            case Sunlight: {
                this.setSunlightRange(lightRange);
                break;
            }
            case RedLight: {
                this.setRedLightRange(lightRange);
                break;
            }
            case GreenLight: {
                this.setGreenLightRange(lightRange);
                break;
            }
            case BlueLight: {
                this.setBlueLightRange(lightRange);
                break;
            }
        }
    }
    
    public void setLightRange(@Nullable final double[] lightRange) {
        this.testLightValue = (lightRange != null);
        if (this.testLightValue) {
            this.lightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.lightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testLightValue = this.isPartialRange(this.lightValueMin, this.lightValueMax);
        }
    }
    
    public void setSkyLightRange(@Nullable final double[] lightRange) {
        this.testSkyLightValue = (lightRange != null);
        if (this.testSkyLightValue) {
            this.skyLightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.skyLightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testSkyLightValue = this.isPartialRange(this.skyLightValueMin, this.skyLightValueMax);
        }
    }
    
    public void setSunlightRange(@Nullable final double[] lightRange) {
        this.testSunlightValue = (lightRange != null);
        if (this.testSunlightValue) {
            this.sunlightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.sunlightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testSunlightValue = this.isPartialRange(this.sunlightValueMin, this.sunlightValueMax);
        }
    }
    
    public void setRedLightRange(@Nullable final double[] lightRange) {
        this.testRedLightValue = (lightRange != null);
        if (this.testRedLightValue) {
            this.redLightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.redLightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testRedLightValue = this.isPartialRange(this.redLightValueMin, this.redLightValueMax);
        }
    }
    
    public void setGreenLightRange(@Nullable final double[] lightRange) {
        this.testGreenLightValue = (lightRange != null);
        if (this.testGreenLightValue) {
            this.greenLightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.greenLightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testGreenLightValue = this.isPartialRange(this.greenLightValueMin, this.greenLightValueMax);
        }
    }
    
    public void setBlueLightRange(@Nullable final double[] lightRange) {
        this.testBlueLightValue = (lightRange != null);
        if (this.testBlueLightValue) {
            this.blueLightValueMin = this.lightPercentageToAbsolute(lightRange[0]);
            this.blueLightValueMax = this.lightPercentageToAbsolute(lightRange[1]);
            this.testBlueLightValue = this.isPartialRange(this.blueLightValueMin, this.blueLightValueMax);
        }
    }
    
    public boolean isTestLightValue() {
        return this.testLightValue;
    }
    
    public boolean isTestSkyLightValue() {
        return this.testSkyLightValue;
    }
    
    public boolean isTestSunlightValue() {
        return this.testSunlightValue;
    }
    
    public boolean isTestRedLightValue() {
        return this.testRedLightValue;
    }
    
    public boolean isTestGreenLightValue() {
        return this.testGreenLightValue;
    }
    
    public boolean isTestBlueLightValue() {
        return this.testBlueLightValue;
    }
    
    public boolean test(@Nonnull final World world, @Nonnull final Vector3d position, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final int x = MathUtil.floor(position.getX());
        final int y = MathUtil.floor(position.getY());
        final int z = MathUtil.floor(position.getZ());
        final WorldTimeResource worldTimeResource = componentAccessor.getResource(WorldTimeResource.getResourceType());
        final WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z));
        return chunk != null && this.test(chunk.getBlockChunk(), x, y, z, worldTimeResource.getSunlightFactor());
    }
    
    public boolean test(@Nullable final BlockChunk blockChunk, final int x, final int y, final int z, final double sunlightFactor) {
        if (blockChunk == null) {
            return false;
        }
        if (this.testLightValue) {
            final byte maxLight = calculateLightValue(blockChunk, x, y, z, sunlightFactor);
            if (!this.testLight(maxLight)) {
                return false;
            }
        }
        if (this.testSkyLightValue) {
            final byte lightValue = blockChunk.getSkyLight(x, y, z);
            if (!this.testSkyLight(lightValue)) {
                return false;
            }
        }
        if (this.testSunlightValue) {
            final byte lightValue = (byte)(blockChunk.getSkyLight(x, y, z) * sunlightFactor);
            if (!this.testSunlight(lightValue)) {
                return false;
            }
        }
        if (this.testRedLightValue) {
            final byte lightValue = blockChunk.getRedBlockLight(x, y, z);
            if (!this.testRedLight(lightValue)) {
                return false;
            }
        }
        if (this.testGreenLightValue) {
            final byte lightValue = blockChunk.getGreenBlockLight(x, y, z);
            if (!this.testGreenLight(lightValue)) {
                return false;
            }
        }
        if (this.testBlueLightValue) {
            final byte lightValue = blockChunk.getBlueBlockLight(x, y, z);
            if (!this.testBlueLight(lightValue)) {
                return false;
            }
        }
        return true;
    }
    
    public boolean testLight(final byte lightValue) {
        return this.test(lightValue, this.lightValueMin, this.lightValueMax);
    }
    
    public boolean testSkyLight(final byte lightValue) {
        return this.test(lightValue, this.skyLightValueMin, this.skyLightValueMax);
    }
    
    public boolean testSunlight(final byte lightValue) {
        return this.test(lightValue, this.sunlightValueMin, this.sunlightValueMax);
    }
    
    public boolean testRedLight(final byte lightValue) {
        return this.test(lightValue, this.redLightValueMin, this.redLightValueMax);
    }
    
    public boolean testGreenLight(final byte lightValue) {
        return this.test(lightValue, this.greenLightValueMin, this.greenLightValueMax);
    }
    
    public boolean testBlueLight(final byte lightValue) {
        return this.test(lightValue, this.blueLightValueMin, this.blueLightValueMax);
    }
    
    public static byte calculateLightValue(@Nonnull final BlockChunk blockChunk, final int x, final int y, final int z, final double sunlightFactor) {
        final int lightValue = blockChunk.getBlockLightIntensity(x, y, z);
        final byte skyLightValue = (byte)(blockChunk.getSkyLight(x, y, z) * sunlightFactor);
        return (byte)Math.max(skyLightValue, lightValue);
    }
    
    private boolean test(final byte lightValue, final byte min, final byte max) {
        return lightValue >= min && lightValue <= max;
    }
    
    private byte lightPercentageToAbsolute(final double light) {
        return (byte)MathUtil.fastRound(light * 0.15);
    }
    
    private boolean isPartialRange(final byte min, final byte max) {
        return min > 0 || max < 15;
    }
}
