package net.beadsproject.touch.surface;
import java.awt.Color;

import net.beadsproject.touch.SurfacePlayer;
import net.beadsproject.touch.event.EnterEvent;
import net.beadsproject.touch.event.ExitEvent;
import net.beadsproject.touch.event.SwitchEvent;
import net.beadsproject.touch.perform.PerformNode;
import processing.core.PApplet;
import processing.core.PImage;

/**
 * PixelSurface is a generic tpye of surface that stores a map from each of its pixels to the performNode that owns that pixel.
 * Hence it uses a little bit of memory but is quite a lot faster than other methods. 
 * 
 * Be sure to bake() the surface before using it! 
 * 
 * @author ben
 */
public class PixelSurface extends Surface {

	PerformNode[][] pixels;
	int width, height;
	
	private PImage img;
	
	public PixelSurface(int w, int h)
	{		
		pixels = new PerformNode[w][h];	
		width = w;
		height = h;
		img = null;
	}
	
	public void set(int x, int y, PerformNode pn)
	{
		pixels[x][y] = pn;
	}
	
	public void bake(PApplet app)
	{
		// generate the PImage
		img = app.createImage(width,height,app.RGB);
		img.loadPixels();
		for(int i=0;i<img.pixels.length;i++)
		{
			int r = i/img.width;
			int c = i%img.width;
			
			if (pixels[c][r]==null) {
				img.pixels[i] = app.color(255,0,255);
			}
			else
			{			
				Color col = new Color(Color.HSBtoRGB(pixels[c][r].uniqueValue(), .75f, .75f));
				img.pixels[i] = app.color(col.getRed(),col.getGreen(),col.getBlue());
			}
		}
		
		img.updatePixels();
	}
	
	@Override
	public void draw(PApplet app) {
		app.image(img,0,0);	
	}
	
	PerformNode getPN(float x, float y)
	{
		int xi = (int)(x*width), yi = (int)(y*height);
		xi = Math.max(xi, 0);
		xi = Math.min(xi, width - 1);
		yi = Math.max(yi, 0);
		yi = Math.min(yi, height - 1);
		PerformNode pn = pixels[xi][yi];	
		return pn;
	}
	
	public void playerPressed(SurfacePlayer sp, float x, float y)
	{
		PerformNode pn = getPN(x,y);
		if (pn!=null)
		{
			event(new EnterEvent(this,pn,x,y));
		}
	}
	
	public void playerReleased(SurfacePlayer sp, float x, float y)
	{
		PerformNode pn = getPN(x,y);
		if (pn!=null)
		{
			event(new ExitEvent(this,pn,x,y));
		}
	}

	@Override
	public void playerMoved(SurfacePlayer sp, float fromX, float fromY,
			float toX, float toY) {
		PerformNode fromPN = getPN(fromX, fromY);
		PerformNode toPN = getPN(toX, toY);
		if(fromPN != null && toPN != null && fromPN != toPN) {
			event(new SwitchEvent(this, fromPN, toPN, toX, toY));
		}
	}

	
}
