package projectzombie.worker;

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

import bdf.file.BdfFileManager;
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 WorkerChunks extends Thread
{
	private static Vector<WorkerChunkTask> chunks_in = new Vector<WorkerChunkTask>();
	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) {
		chunks_in.add(new WorkerChunkTaskGenerate(layergen, layer, chunk, rand, pos.copy()));
	}
	
	public static void loadChunk(String path, Layer layer, Vec2i pos) {
		chunks_in.add(new WorkerChunkTaskLoad(path, layer, pos.copy()));
	}

	public static void saveChunk(String path, Vec2i pos, Chunk chunk, int id) {
		chunks_in.add(new WorkerChunkTaskSave(path, pos.copy(), chunk, id));
	}
	
	public static Vector<Chunk> getChunks() {
		return chunks_out.getAndSet(new Vector<Chunk>());
	}
	
	public static boolean hasChunk(Vec2i cpos)
	{
		boolean has[] = {false};
		
		chunks_in.forEach(c ->
		{
			if(
					(c instanceof WorkerChunkTaskGenerate ||
					c instanceof WorkerChunkTaskLoad) &&
					c.pos.equal(cpos))
			{
				has[0] = true;
			}
		});
		
		return has[0];
	}
	
	public WorkerChunks() {
		chunks_out.set(new Vector<Chunk>());
	}
	
	private synchronized WorkerChunkTask getNextIfAvailable()
	{
		if(chunks_in.size() == 0) {
			return null;
		} else {
			return chunks_in.remove(0);
		}
	}
	
	@Override
	public void run()
	{
		try
		{
			while(Main.running)
			{
				WorkerChunkTask ct = getNextIfAvailable();
				
				if(ct == null) {
					Thread.sleep(10);
					continue;
				}
				
				// Generate a new chunk
				if(ct instanceof WorkerChunkTaskGenerate)
				{
					WorkerChunkTaskGenerate ct_g = (WorkerChunkTaskGenerate)ct;
					
					ct_g.layergen.generateChunk(ct_g.chunk, ct_g.layer, ct_g.rand, ct_g.pos);
					
					chunks_out.get().add(ct_g.chunk);
				}
				
				// Load an existing chunk
				if(ct instanceof WorkerChunkTaskLoad)
				{
					WorkerChunkTaskLoad ct_l = (WorkerChunkTaskLoad)ct;
					
					if(ct_l.path == null) {
						System.out.println("ChunkLoad: Path is NULL");
						continue;
					}
					
					String path = (
							"./saves/" + ct_l.path + "/c_" + ct_l.layer.id +
							"_" + ct_l.pos.x + "_" + ct_l.pos.y + ".bdf");
					
					BdfFileManager reader = new BdfFileManager(path, true);
					
					Chunk chunk = new Chunk(ct_l.layer, ct_l.pos, reader.getObject());
					
					chunks_out.get().add(chunk);
				}
				
				// Save a chunk
				if(ct instanceof WorkerChunkTaskSave)
				{
					WorkerChunkTaskSave ct_s = (WorkerChunkTaskSave)ct;
					
					if(ct_s.path == null) {
						System.out.println("ChunkSave: Path is NULL");
						continue;
					}
					
					String path = (
							"./saves/" + ct_s.path + "/c_" + ct_s.id +
							"_" + ct_s.pos.x + "_" + ct_s.pos.y + ".bdf");
					
					BdfFileManager reader = new BdfFileManager(path, true);
					
					ct_s.chunk.BdfClassSave(reader.getObject());
					
					reader.saveDatabase();
				}
			}
		}
		
		catch(InterruptedException e) {
			e.printStackTrace();
		}
	}

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