package speiger.src.coreengine.utils.profiler;

import java.util.ArrayList;
import java.util.List;

import speiger.src.collections.longs.queues.LongArrayFIFOQueue;
import speiger.src.collections.longs.queues.LongPriorityQueue;
import speiger.src.coreengine.utils.profiler.IProfiler.IProfilerEntry;

public class ProfilerEntry implements IProfilerEntry {
	String name;
	String pathName;
	IProfiler owner;
	IProfilerEntry parent;
	List<IProfilerEntry> children = new ArrayList<IProfilerEntry>();
	int debth = 0;
	int totalTicks = 0;
	long maxTime = Long.MIN_VALUE;
	long minTime = Long.MAX_VALUE;
	long average = 0L;
	LongPriorityQueue entries = new LongArrayFIFOQueue();
	long startTime = 0L;
	long currentTime = 0L;
	boolean didTick = false;
	
	public ProfilerEntry(String name, IProfiler owner) {
		this.name = name;
		pathName = name;
		this.owner = owner;
	}
	
	public void addChild(ProfilerEntry child) {
		if(child != null) {
			children.add(child);
			child.setParent(this);
		}
	}
	
	private void setParent(ProfilerEntry parent) {
		this.parent = parent;
		debth = parent.debth + 1;
		pathName = parent.pathName+"/"+name;
	}
	
	public void start() {
		startTime = System.nanoTime();
	}
	
	public void stop() {
		currentTime += (System.nanoTime() - startTime);
		didTick = true;
	}
	
	public void onFrameFinished(boolean end) {
		if(!didTick) {
			if(end && totalTicks++ >= 10) {
				minTime = Long.MAX_VALUE;
				maxTime = Long.MIN_VALUE;
				totalTicks = 0;
			}
			return;
		}
		didTick = false;
		average += currentTime;
		entries.enqueue(currentTime);
		if(entries.size() > 100) { average -= entries.dequeue(); }
		currentTime = average / entries.size();
		minTime = Math.min(minTime, currentTime);
		maxTime = Math.max(maxTime, currentTime);
		currentTime = 0;
		if(end && totalTicks++ >= 10) {
			minTime = currentTime;
			maxTime = currentTime;
			totalTicks = 0;
		}
	}
	
	@Override
	public String getName() { return name; }
	@Override
	public String getPathName() { return pathName; }
	@Override
	public long getMinTime() { return minTime; }
	@Override
	public long getNanoTime() { return entries.isEmpty() ? 0L : average / entries.size(); }
	@Override
	public long getMaxTime() { return maxTime; }
	@Override
	public int getDebth() { return debth; }
	@Override
	public int getChildCount() { return children.size(); }
	@Override
	public IProfilerEntry getChild(int index) { return children.get(index); }
	@Override
	public IProfilerEntry getParent() { return parent; }
	@Override
	public IProfiler getOwner() { return owner; }
}
