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

package com.hypixel.hytale.builtin.hytalegenerator.threadindexer;

import java.util.function.Supplier;
import java.util.Collections;
import java.util.ArrayList;
import javax.annotation.Nonnull;
import java.util.List;

public class WorkerIndexer
{
    private final int workerCount;
    @Nonnull
    private final List<Id> ids;
    
    public WorkerIndexer(final int workerCount) {
        if (workerCount <= 0) {
            throw new IllegalArgumentException("workerCount must be > 0");
        }
        this.workerCount = workerCount;
        final List<Id> tempIds = new ArrayList<Id>(workerCount);
        for (int i = 0; i < workerCount; ++i) {
            tempIds.add(new Id(i));
        }
        this.ids = Collections.unmodifiableList((List<? extends Id>)tempIds);
    }
    
    public int getWorkerCount() {
        return this.workerCount;
    }
    
    @Nonnull
    public List<Id> getWorkedIds() {
        return this.ids;
    }
    
    @Nonnull
    public Session createSession() {
        return new Session();
    }
    
    public class Session
    {
        private int index;
        
        public Session() {
            this.index = 0;
        }
        
        public Id next() {
            if (this.index >= WorkerIndexer.this.workerCount) {
                throw new IllegalStateException("worker count exceeded");
            }
            return WorkerIndexer.this.ids.get(this.index++);
        }
        
        public boolean hasNext() {
            return this.index < WorkerIndexer.this.workerCount;
        }
    }
    
    public static class Id
    {
        public static final int UNKNOWN_THREAD_ID = -1;
        public static final Id UNKNOWN;
        public final int id;
        
        private Id(final int id) {
            this.id = id;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return String.valueOf(this.id);
        }
        
        static {
            UNKNOWN = new Id(-1);
        }
    }
    
    public static class Data<T>
    {
        private T[] data;
        private Supplier<T> initialize;
        
        public Data(final int size, @Nonnull final Supplier<T> initialize) {
            this.data = (T[])new Object[size];
            this.initialize = initialize;
        }
        
        public boolean isValid(@Nonnull final Id id) {
            return id != null && id.id < this.data.length && id.id >= 0;
        }
        
        @Nonnull
        public T get(@Nonnull final Id id) {
            if (!this.isValid(id)) {
                throw new IllegalArgumentException("Invalid thread id " + String.valueOf(id));
            }
            if (this.data[id.id] == null) {
                this.data[id.id] = this.initialize.get();
                assert this.data[id.id] != null;
            }
            return this.data[id.id];
        }
    }
}
