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

package com.hypixel.hytale.builtin.adventure.shop.barter;

import com.hypixel.hytale.codec.codecs.array.ArrayCodec;
import com.hypixel.hytale.codec.validation.Validator;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.Codec;
import java.util.Iterator;
import java.util.Collection;
import java.util.Arrays;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import com.hypixel.hytale.codec.builder.BuilderCodec;

public class PoolTradeSlot extends TradeSlot
{
    public static final BuilderCodec<PoolTradeSlot> CODEC;
    protected int slotCount;
    protected WeightedTrade[] trades;
    
    public PoolTradeSlot(final int slotCount, @Nonnull final WeightedTrade[] trades) {
        this.slotCount = 1;
        this.trades = WeightedTrade.EMPTY_ARRAY;
        this.slotCount = slotCount;
        this.trades = trades;
    }
    
    protected PoolTradeSlot() {
        this.slotCount = 1;
        this.trades = WeightedTrade.EMPTY_ARRAY;
    }
    
    public int getPoolSlotCount() {
        return this.slotCount;
    }
    
    @Nonnull
    public WeightedTrade[] getTrades() {
        return this.trades;
    }
    
    @Nonnull
    @Override
    public List<BarterTrade> resolve(@Nonnull final Random random) {
        final List<BarterTrade> result = new ObjectArrayList<BarterTrade>(this.slotCount);
        if (this.trades.length == 0) {
            return result;
        }
        final ObjectArrayList<WeightedTrade> available = new ObjectArrayList<WeightedTrade>(this.trades.length);
        available.addAll((Collection<?>)Arrays.asList(this.trades));
        for (int toSelect = Math.min(this.slotCount, available.size()), i = 0; i < toSelect; ++i) {
            final int selectedIndex = this.selectWeightedIndex(available, random);
            if (selectedIndex >= 0) {
                final WeightedTrade selected = available.remove(selectedIndex);
                result.add(selected.toBarterTrade(random));
            }
        }
        return result;
    }
    
    @Override
    public int getSlotCount() {
        return this.slotCount;
    }
    
    private int selectWeightedIndex(@Nonnull final List<WeightedTrade> trades, @Nonnull final Random random) {
        if (trades.isEmpty()) {
            return -1;
        }
        double totalWeight = 0.0;
        for (final WeightedTrade trade : trades) {
            totalWeight += trade.getWeight();
        }
        if (totalWeight <= 0.0) {
            return random.nextInt(trades.size());
        }
        final double roll = random.nextDouble() * totalWeight;
        double cumulative = 0.0;
        for (int i = 0; i < trades.size(); ++i) {
            cumulative += trades.get(i).getWeight();
            if (roll < cumulative) {
                return i;
            }
        }
        return trades.size() - 1;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "PoolTradeSlot{slotCount=" + this.slotCount + ", trades=" + Arrays.toString(this.trades);
    }
    
    static {
        CODEC = BuilderCodec.builder(PoolTradeSlot.class, PoolTradeSlot::new).append(new KeyedCodec<Integer>("SlotCount", Codec.INTEGER), (slot, count) -> slot.slotCount = count, slot -> slot.slotCount).addValidator((Validator<? super Integer>)Validators.greaterThanOrEqual(1)).add().append(new KeyedCodec("Trades", new ArrayCodec(WeightedTrade.CODEC, WeightedTrade[]::new)), (slot, trades) -> slot.trades = trades, slot -> slot.trades).addValidator(Validators.nonNull()).add().build();
    }
}
