package projectzombie.worker;

import java.util.Random;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;


import bdf.types.BdfReader;
import gl_engine.vec.Vec2i;
import projectzombie.Main;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;
import projectzombie.world.layer.layergen.LayerGen;

public class WorkerTasks extends Thread
{
	private static Vector<WorkerTask> tasks_in = new Vector<WorkerTask>();
	private static AtomicReference<Vector<Chunk>> chunks_out = new AtomicReference<Vector<Chunk>>();
	
	public static void generateChunk(LayerGen layergen, Layer layer, Chunk chunk, Random rand, Vec2i pos) {
		tasks_in.add(new WorkerTaskChunkGenerate(layergen, layer, chunk, rand, pos.copy()));
	}
	
	public static void loadChunk(String path, Layer layer, Vec2i pos) {
		tasks_in.add(new WorkerTaskChunkLoad(path, layer, pos.copy()));
	}

	public static void saveChunk(String path, Vec2i pos, Chunk chunk, int id) {
		tasks_in.add(new WorkerTaskChunkSave(path, pos.copy(), chunk, id));
	}
	
	public static void saveToFile(String path, BdfReader reader) {
		tasks_in.add(new WorkerTaskFile(path, reader));
	}
	
	public synchronized static Vector<Chunk> getChunks() {
		return chunks_out.getAndSet(new Vector<Chunk>());
	}
	
	synchronized static void addChunkOut(Chunk chunk) {
		chunks_out.get().add(chunk);
	}
	
	public static boolean hasChunk(Vec2i cpos)
	{
		boolean has[] = {false};
		
		tasks_in.forEach(c ->
		{
			if(
					(c instanceof WorkerTaskChunkGenerate ||
					c instanceof WorkerTaskChunkLoad) &&
					((WorkerTaskChunk)c).pos.equal(cpos))
			{
				has[0] = true;
			}
		});
		
		return has[0];
	}
	
	public WorkerTasks() {
		chunks_out.set(new Vector<Chunk>());
	}
	
	private static synchronized WorkerTask getNextIfAvailable()
	{
		if(tasks_in.size() == 0) {
			return null;
		} else {
			return tasks_in.remove(0);
		}
	}
	
	@Override
	public void run()
	{
		try
		{
			while(Main.running)
			{
				WorkerTask ct = getNextIfAvailable();
				
				if(ct == null) {
					Thread.sleep(10);
					continue;
				}
				
				ct.run();
			}
		}
		
		catch(InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static boolean isDone() {
		return tasks_in.size() == 0;
	}
}
