package net.minecraft.gametest.framework;

import org.apache.logging.log4j.LogManager;
import net.minecraft.core.Vec3i;
import java.util.Iterator;
import com.google.common.collect.Lists;
import java.util.Collection;
import com.mojang.datafixers.util.Pair;
import java.util.List;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.BlockPos;
import org.apache.logging.log4j.Logger;

public class GameTestBatchRunner {
    private static final Logger LOGGER;
    private final BlockPos startPos;
    private final ServerLevel level;
    private final GameTestTicker testTicker;
    private final List<GameTestInfo> allTestInfos;
    private final List<Pair<GameTestBatch, Collection<GameTestInfo>>> batches;
    private MultipleTestTracker currentBatchTracker;
    private int currentBatchIndex;
    private BlockPos.MutableBlockPos nextTestPos;
    private int maxDepthOnThisRow;
    
    public GameTestBatchRunner(final Collection<GameTestBatch> collection, final BlockPos fk, final ServerLevel xd, final GameTestTicker jc) {
        this.allTestInfos = Lists.newArrayList();
        this.batches = Lists.newArrayList();
        this.currentBatchIndex = 0;
        this.maxDepthOnThisRow = 0;
        this.nextTestPos = new BlockPos.MutableBlockPos(fk);
        this.startPos = fk;
        this.level = xd;
        this.testTicker = jc;
        final Collection<GameTestInfo> collection2;
        final Collection<TestFunction> collection3;
        final Iterator<TestFunction> iterator;
        TestFunction jk7;
        GameTestInfo iw8;
        collection.forEach(ir -> {
            collection2 = Lists.newArrayList();
            collection3 = ir.getTestFunctions();
            collection3.iterator();
            while (iterator.hasNext()) {
                jk7 = iterator.next();
                iw8 = new GameTestInfo(jk7, xd);
                collection2.add(iw8);
                this.allTestInfos.add(iw8);
            }
            this.batches.add((Pair<GameTestBatch, Collection<GameTestInfo>>)Pair.of(ir, collection2));
        });
    }
    
    public List<GameTestInfo> getTestInfos() {
        return this.allTestInfos;
    }
    
    public void start() {
        this.runBatch(0);
    }
    
    private void runBatch(final int integer) {
        this.currentBatchIndex = integer;
        this.currentBatchTracker = new MultipleTestTracker();
        if (integer >= this.batches.size()) {
            return;
        }
        final Pair<GameTestBatch, Collection<GameTestInfo>> pair3 = this.batches.get(this.currentBatchIndex);
        final GameTestBatch ir4 = (GameTestBatch)pair3.getFirst();
        final Collection<GameTestInfo> collection5 = (Collection<GameTestInfo>)pair3.getSecond();
        this.createStructuresForBatch(collection5);
        ir4.runBeforeBatchFunction(this.level);
        final String string6 = ir4.getName();
        GameTestBatchRunner.LOGGER.info("Running test batch '" + string6 + "' (" + collection5.size() + " tests)...");
        collection5.forEach(iw -> {
            this.currentBatchTracker.add(iw);
            this.currentBatchTracker.setListener(new GameTestListener() {
                @Override
                public void testStructureLoaded(final GameTestInfo iw) {
                }
                
                @Override
                public void testFailed(final GameTestInfo iw) {
                    GameTestBatchRunner.this.testCompleted(iw);
                }
            });
            GameTestRunner.runTest(iw, this.testTicker);
        });
    }
    
    private void testCompleted(final GameTestInfo iw) {
        if (this.currentBatchTracker.isDone()) {
            this.runBatch(this.currentBatchIndex + 1);
        }
    }
    
    private void createStructuresForBatch(final Collection<GameTestInfo> collection) {
        int integer3 = 0;
        for (final GameTestInfo iw5 : collection) {
            final BlockPos fk6 = new BlockPos(this.nextTestPos);
            iw5.assignPosition(fk6);
            StructureUtils.spawnStructure(iw5.getStructureName(), fk6, 2, this.level, true);
            final BlockPos fk7 = iw5.getStructureSize();
            final int integer4 = (fk7 == null) ? 1 : fk7.getX();
            final int integer5 = (fk7 == null) ? 1 : fk7.getZ();
            this.maxDepthOnThisRow = Math.max(this.maxDepthOnThisRow, integer5);
            this.nextTestPos.move(integer4 + 4, 0, 0);
            if (integer3++ % 8 == 0) {
                this.nextTestPos.move(0, 0, this.maxDepthOnThisRow + 5);
                this.nextTestPos.setX(this.startPos.getX());
                this.maxDepthOnThisRow = 0;
            }
        }
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
