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

package com.hypixel.hytale.component.task;

import java.util.Arrays;
import com.hypixel.hytale.common.util.ArrayUtil;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
import java.util.concurrent.CountedCompleter;
import java.util.function.IntConsumer;

public class ParallelTask<D extends IntConsumer> extends CountedCompleter<Void>
{
    private final Supplier<D> supplier;
    @Nonnull
    private ParallelRangeTask<D>[] subTasks;
    private int size;
    private volatile boolean running;
    
    public ParallelTask(final Supplier<D> supplier) {
        this(null, supplier);
    }
    
    public ParallelTask(final CountedCompleter<?> completer, final Supplier<D> supplier) {
        super(completer);
        this.subTasks = new ParallelRangeTask[0];
        this.supplier = supplier;
    }
    
    @Override
    public void reinitialize() {
        if (this.running) {
            throw new IllegalStateException("Parallel task has already been started");
        }
        super.reinitialize();
    }
    
    public void init() {
        this.reinitialize();
        this.size = 0;
    }
    
    public ParallelRangeTask<D> appendTask() {
        if (this.running) {
            throw new IllegalStateException("Parallel task has already been started");
        }
        if (this.subTasks.length <= this.size) {
            this.subTasks = Arrays.copyOf(this.subTasks, ArrayUtil.grow(this.size));
            for (int i = this.size; i < this.subTasks.length; ++i) {
                this.subTasks[i] = new ParallelRangeTask<D>(this, this.supplier);
            }
        }
        return this.subTasks[this.size++];
    }
    
    public int size() {
        return this.size;
    }
    
    public ParallelRangeTask<D> get(final int i) {
        return this.subTasks[i];
    }
    
    @Override
    public void compute() {
        this.setPendingCount(this.size - 1);
        for (int i = 0; i < this.size - 1; ++i) {
            this.subTasks[i].fork();
        }
        this.subTasks[this.size - 1].compute();
    }
    
    public void doInvoke() {
        this.running = true;
        for (int i = 0; i < this.size; ++i) {
            this.subTasks[i].running = true;
        }
        this.invoke();
        for (int i = 0; i < this.size; ++i) {
            this.subTasks[i].running = false;
        }
        this.running = false;
    }
}
