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

package com.hypixel.hytale.server.core.modules.collision;

import java.util.Comparator;
import javax.annotation.Nullable;
import java.util.Objects;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import java.util.List;

public class CollisionDataArray<T>
{
    @Nonnull
    private final List<T> array;
    private final Supplier<T> supplier;
    private final Consumer<T> dispose;
    private final List<T> freeList;
    private int head;
    
    public CollisionDataArray(final Supplier<T> supplier, final Consumer<T> dispose, final List<T> freeList) {
        this.array = new ObjectArrayList<T>();
        Objects.requireNonNull(supplier, "Must provide supplier for CollisionDataArray");
        this.supplier = supplier;
        this.dispose = dispose;
        this.freeList = freeList;
        this.head = 0;
    }
    
    public int getCount() {
        return this.array.size() - this.head;
    }
    
    public T alloc() {
        T result;
        if (this.freeList.isEmpty()) {
            result = this.supplier.get();
        }
        else {
            final int last = this.freeList.size() - 1;
            result = this.freeList.get(last);
            this.freeList.remove(last);
        }
        this.array.add(result);
        return result;
    }
    
    public void reset() {
        final int count = this.array.size();
        if (count > 0) {
            if (this.dispose != null) {
                for (int i = 0; i < count; ++i) {
                    final T value = this.array.get(i);
                    this.dispose.accept(value);
                    this.freeList.add(value);
                }
            }
            else {
                for (int i = 0; i < count; ++i) {
                    final T value = this.array.get(i);
                    this.freeList.add(value);
                }
            }
            this.array.clear();
            this.head = 0;
        }
    }
    
    @Nullable
    public T getFirst() {
        return (this.head < this.array.size()) ? this.array.get(this.head) : null;
    }
    
    @Nullable
    public T forgetFirst() {
        ++this.head;
        return this.getFirst();
    }
    
    public boolean isEmpty() {
        return this.array.isEmpty();
    }
    
    public void sort(final Comparator<? super T> comparator) {
        this.array.sort(comparator);
    }
    
    public void remove(final int l) {
        final int index = this.head + l;
        if (index < this.array.size()) {
            this.freeList.add(this.array.get(index));
            this.array.remove(index);
        }
    }
    
    public int size() {
        return this.array.size() - this.head;
    }
    
    public T get(final int i) {
        return this.array.get(this.head + i);
    }
}
