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

package com.hypixel.hytale.builtin.hytalegenerator.framework.cartas;

import java.util.Collection;
import java.util.ArrayList;
import java.util.HashMap;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import javax.annotation.Nullable;
import com.hypixel.hytale.builtin.hytalegenerator.framework.math.Calculator;
import java.util.Objects;
import javax.annotation.Nonnull;
import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer;
import java.util.List;
import java.util.Map;
import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.TriDoubleFunction;
import com.hypixel.hytale.builtin.hytalegenerator.framework.interfaces.functions.TriCarta;

public class ImageCarta<R> extends TriCarta<R>
{
    private int[] rgbArray;
    private int width;
    private int height;
    private TriDoubleFunction<Double> functionX;
    private TriDoubleFunction<Double> functionY;
    private Map<Integer, R> rgbToTerrainMap;
    private List<R> allPossibleValues;
    
    private ImageCarta() {
    }
    
    @Nullable
    @Override
    public R apply(final int x, final int y, final int z, @Nonnull final WorkerIndexer.Id tHreadId) {
        Objects.requireNonNull(x);
        Objects.requireNonNull(y);
        Objects.requireNonNull(z);
        int sampleX = Calculator.toNearestInt(this.functionX.apply(x, y, z) * this.width);
        sampleX = ((sampleX < 0) ? 0 : Math.min(sampleX, this.width - 1));
        int sampleY = Calculator.toNearestInt(this.functionY.apply(x, y, z) * this.height);
        sampleY = ((sampleY < 0) ? 0 : Math.min(sampleY, this.height - 1));
        final int rgb = this.rgbArray[sampleX + sampleY * this.width];
        if (!this.rgbToTerrainMap.containsKey(rgb)) {
            return null;
        }
        return this.rgbToTerrainMap.get(rgb);
    }
    
    @Override
    public List<R> allPossibleValues() {
        return this.allPossibleValues;
    }
    
    public static int greenFromRgb(final int rgb) {
        return (rgb & 0xFF00) >> 8;
    }
    
    public static int redFromRgb(final int rgb) {
        return (rgb & 0xFF0000) >> 16;
    }
    
    public static int blueFromRgb(final int rgb) {
        return rgb & 0xFF;
    }
    
    public static int coloursToRgb(final int red, final int green, final int blue) {
        int rgb = red << 16;
        rgb += green << 8;
        rgb += blue;
        return rgb;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "ImageCarta{rgbArray=" + Arrays.toString(this.rgbArray) + ", width=" + this.width + ", height=" + this.height + ", functionX=" + String.valueOf(this.functionX) + ", functionY=" + String.valueOf(this.functionY) + ", rgbToTerrainMap=" + String.valueOf(this.rgbToTerrainMap) + ", allPossibleValues=" + String.valueOf(this.allPossibleValues);
    }
    
    public static class Builder<R>
    {
        @Nonnull
        private final Map<Integer, R> rgbToTerrainMap;
        private BufferedImage bufferedImage;
        private boolean bufferedImageCheck;
        private TriDoubleFunction<Double> noiseX;
        private TriDoubleFunction<Double> noiseY;
        private boolean noiseCheck;
        
        public Builder() {
            this.rgbToTerrainMap = new HashMap<Integer, R>();
        }
        
        @Nonnull
        public ImageCarta<R> build() {
            if (!this.bufferedImageCheck || !this.noiseCheck) {
                throw new IllegalStateException("incomplete builder");
            }
            final ImageCarta<R> instance = new ImageCarta<R>();
            instance.rgbToTerrainMap = this.rgbToTerrainMap;
            instance.functionX = this.noiseX;
            instance.functionY = this.noiseY;
            (instance.allPossibleValues = (List<R>)new ArrayList<Object>(1)).addAll((Collection<? extends R>)this.rgbToTerrainMap.values());
            instance.width = this.bufferedImage.getWidth();
            instance.height = this.bufferedImage.getHeight();
            instance.rgbArray = new int[instance.width * instance.height];
            for (int x = 0; x < instance.width; ++x) {
                for (int y = 0; y < instance.height; ++y) {
                    instance.rgbArray[x + y * instance.width] = (0xFFFFFF & this.bufferedImage.getRGB(x, y));
                }
            }
            return instance;
        }
        
        @Nonnull
        public Builder<R> withImage(final BufferedImage image) {
            Objects.requireNonNull(image);
            this.bufferedImage = image;
            this.bufferedImageCheck = true;
            return this;
        }
        
        @Nonnull
        public Builder<R> withNoiseFunctions(final TriDoubleFunction<Double> noiseX, final TriDoubleFunction<Double> noiseY) {
            Objects.requireNonNull(noiseX);
            Objects.requireNonNull(noiseY);
            this.noiseX = noiseX;
            this.noiseY = noiseY;
            this.noiseCheck = true;
            return this;
        }
        
        @Nonnull
        public Builder<R> addTerrainRgb(final int rgb, @Nonnull final R terrain) {
            this.rgbToTerrainMap.put(rgb, terrain);
            return this;
        }
    }
}
