package com.wildex999.tickdynamic.listinject;

import net.minecraft.profiler.Profiler;

/*
 * This profiler will note where the world is while ticking Entities
 * when using a for loop for iterating.
 * This will allow us to be 100% accurate while the world is iterating, as we would know
 * whether we are ticking, or looping the list from inside a ticking entity.
 * 
 * This does however add a bit of an overhead with the function calls and String compare.
 */


public class CustomProfiler extends Profiler {

	public enum Stage {
		None, //Just pass on to original
		BeforeLoop, //World Tick has started
		InLoop, //We have started looping entities
		InTick, //We are currently ticking a single entity
		InRemove //Removing dead Entity
	}
	
	public final Profiler original;
	public Stage stage;
	public boolean reachedTile; //Set to true when starting to tick TileEntities
	
	
	private int depthCount; //start and end can be called inside Entity tick, we have to track it
	
	public CustomProfiler(Profiler originalProfiler) {
		this.original = originalProfiler;
		this.stage = Stage.None;
		this.reachedTile = false;
	}

	//Set new Stage, with the ability to log the change for debugging
	public void setStage(Stage stage) {
		//System.out.println("Stage change: " + this.stage + " -> " + stage);
		this.stage = stage;
	}
	
	@Override
    public void startSection(String sectionName)
    {

		switch(stage) {
		case None:
			break;
			
		case BeforeLoop:
			if(sectionName.equals("regular"))
				setStage(Stage.InLoop);
			break;
			
		case InLoop:
			if(sectionName.equals("tick")) {
				setStage(Stage.InTick);
				depthCount = 0;
			} else if(sectionName.equals("remove")) {
				setStage(Stage.InRemove);
				depthCount = 0;
			} else if(sectionName.equals("blockEntities")) {
				setStage(Stage.None); //Done ticking Entities
				reachedTile = true;
			}
			break;
			
		case InTick:
			//Sometimes the InTick isn't correctly closed, allow some leeway here
			if(depthCount <= 1 && sectionName.equals("remove")) {
				setStage(Stage.InRemove);
				depthCount = 0;
				break;
			}
		case InRemove:
			depthCount++;
			break;
		}
		
		original.startSection(sectionName);
    }
	
	@Override
	public void endSection() {
		switch(stage) {
		case InTick:
			if(depthCount-- <= 0)
				setStage(Stage.InLoop);
			break;
		case InRemove:
			if(depthCount-- <= 0)
				setStage(Stage.InLoop);
			break;
		default:
			break;
		}
		original.endSection();
	}
	
}