package projectzombie.worker;

import java.util.concurrent.atomic.AtomicReference;

import projectzombie.Main;
import projectzombie.display.DisplayLighting;
import projectzombie.task.Task;

public class WorkerLighting extends Thread
{
	private class LightingTask {
		float[] lights;
		int width;
		int height;
		int x;
		int y;
	}
	
	private AtomicReference<LightingTask> task = new AtomicReference<WorkerLighting.LightingTask>();
	
	public void processLighting(float[] lights, int width, int height, int x, int y)
	{
		LightingTask task = new LightingTask();
		task.lights = lights;
		task.width = width;
		task.height = height;
		task.x = x;
		task.y = y;
		
		this.task.set(task);
	}
	
	private float getLight(LightingTask task, int x, int y) {
		return task.lights[(x + y * task.width) * 2];
	}
	
	private void setLight(LightingTask task, int x, int y, float v) {
		task.lights[(x + y * task.width) * 2] = v;
	}
	
	private float getTransparency(LightingTask task, int x, int y) {
		return task.lights[(x + y * task.width) * 2 + 1];
	}
	
	public void calculateLight(LightingTask task, int x, int y, float level, boolean ignore)
	{
		if(x < 0 || y < 0 || x >= task.width || y >= task.height) {
			return;
		}
		
		float level_current = getLight(task, x, y);
		
		if(level_current >= level && !ignore) {
			return;
		}
		
		setLight(task, x, y, level);
		
		float level_next = level - getTransparency(task, x, y);
		int[] adjacent = new int[] {
				x+1, y+0,
				x+0, y+1,
				x-1, y-0,
				x-0, y-1,
		};
		
		for(int i=0;i<8;i+=2) {
			calculateLight(task, adjacent[i], adjacent[i+1], level_next, false);
		}
	}

	
	@Override
	public void run()
	{
		try
		{
			while(Main.running)
			{
				LightingTask task = this.task.getAndSet(null);
				
				if(task != null)
				{
					for(int x=0;x<task.width;x++) {
						for(int y=0;y<task.height;y++)
						{
							float level = getLight(task, x, y);
							
							if(level == 0) {
								continue;
							}
							
							calculateLight(task, x, y, level, true);
						}
					}
					
					DisplayLighting.updateLighting(task.lights, task.x, task.y, task.width, task.height);
				}
				
				else {
					Thread.sleep(10);
				}
			}
		}
		
		catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
}
