package net.beadsproject.touch.examples;

import java.awt.MouseInfo;
import java.awt.Point;

import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.touch.SurfacePlayer;
import net.beadsproject.touch.event.EnterEvent;
import net.beadsproject.touch.event.Event;
import net.beadsproject.touch.event.EventListener;
import net.beadsproject.touch.event.ExitEvent;
import net.beadsproject.touch.event.SwitchEvent;
import net.beadsproject.touch.perform.PerformNode;
import net.beadsproject.touch.perform.PerformTree;
import net.beadsproject.touch.surface.Surface;
import net.beadsproject.touch.surface.SurfaceGenerator;
import processing.core.PApplet;

public class SurfaceGenerationApp extends PApplet {
	
	Surface surface;
	float ox, oy; // old mousex, mousey;
	SurfacePlayer sp; // the user
	
	public class EL implements EventListener
	{
		public void receiveEvent(Event e) {
			if (e instanceof EnterEvent)
			{
				EnterEvent ee = (EnterEvent)e;
				PerformNode.enterNode(ee.pn());
			}
			else if (e instanceof ExitEvent)
			{
				ExitEvent ee = (ExitEvent)e;
				PerformNode.exitNode(ee.pn());				
			}
			else if (e instanceof SwitchEvent)
			{
				SwitchEvent se = (SwitchEvent)e;
				PerformNode.switchNodes(se.from(), se.to());
			}	
		}
	}
	
	public void setup()
	{
		size(800,800);		
		
		sp = new SurfacePlayer();
		
		// PerformTree pt = ExampleTree.example4();
		//String filename =  "D:\\audio\\crash test audio\\chopped live sounds\\Bongos\\BONGOROL.WAV"; 
		// String filename = "D:\\Music\\gammaBrosTheme.mp3";
		
		switch (3) // choose the demo
		{
			case -1:
			{
				String filename = "D:\\audio\\crash test audio\\chopped live sounds\\Bongos\\BONGOROL.WAV";
				PerformTree pt = ExampleTree.exampleScatterPartsTree(filename,10);
				pt.computeUniqueValues();
				surface = SurfaceGenerator.UniformVoronoiTwo(pt);
				// surface = new RectangleSurface(pt);
				print(pt.toString());				
				break;
			}
			
			case 0:
			{
				String filename = "D:\\audio\\crash test audio\\chopped live sounds\\Bongos\\BONGOROL.WAV";
				PerformTree pt = ExampleTree.exampleScatterPartsTree(filename,20);
				pt.computeUniqueValues();
				surface = SurfaceGenerator.UniformVoronoi(pt);
				// surface = new RectangleSurface(pt);
				print(pt.toString());				
				break;
			}
		
			case 1: // testing
			{
				// String filename = "D:\\audio\\crash test audio\\chopped live sounds\\Bongos\\BONGOROL.WAV";
				// String filename = "D:\\Music\\Alog\\Amateur\\02 A Throne For The Common Man.mp3";
				String filename = "D:\\Music\\gammaBrosTheme.mp3";
				PerformTree pt = ExampleTree.exampleScatterPartsTree(filename,100);
				pt.computeUniqueValues();
				surface = SurfaceGenerator.UniformVoronoiTwo(pt);
				// surface = new RectangleSurface(pt);
				print(pt.toString());							
				break;
			}
			
			case 2: // wicked demo
			{
				String filename = "D:\\Music\\Alog\\Amateur\\02 A Throne For The Common Man.mp3";
				PerformTree pt = ExampleTree.exampleScatterPartsTree(filename,50);
				
				// surface = SurfaceGenerator.BasicRecursiveCircles(pt);
				//surface = SurfaceGenerator.RandomCircles(pt);
				//surface = SurfaceGenerator.BasicRecursiveVoronoi(pt);
				//surface = SurfaceGenerator.RandomVoronoi(pt);
				surface = SurfaceGenerator.UniformVoronoi(pt);
				
				break;
			}			
			
			case 3: // mr b's exciting 909 
			{
				final AudioContext ac = new AudioContext(128);
				PerformTree pt = ExampleTree2.example1(ac);
//				PerformTree pt = ExampleTree3.example1(ac);
				pt.computeUniqueValues();
				System.out.println(pt.toString());
				
//				surface = SurfaceGenerator.RandomVoronoi(pt);
//				surface = SurfaceGenerator.BasicRecursiveCircles(pt);
				surface = SurfaceGenerator.UniformVoronoiTwo(pt);
//				setupAudioRateMousePoller(ac);
				break;
			}
			
			case 4: 
			{
				final AudioContext ac = new AudioContext(128);
				PerformTree pt = ExampleOscBankFromVoice.example1(ac);
				pt.computeUniqueValues();
				System.out.println(pt.toString());

//				surface = SurfaceGenerator.RandomCircles(pt);
//				surface = SurfaceGenerator.BasicRecursiveCircles(pt);
				surface = SurfaceGenerator.UniformVoronoiTwo(pt);
//				setupAudioRateMousePoller(ac);
				break;
			}
			
		}
				
		EL el = new EL();
		surface.setEventListener(el);
		
		ox = 0;
		oy = 0;
	}
	
	public void draw()
	{
		scale(width,height);
		strokeWeight(1f/width);
		noStroke();
		surface.draw(this);
	}
	
	public void setupAudioRateMousePoller(AudioContext ac) {
		UGen mousePoller = new UGen(ac) {
			public void calculateBuffer() {
				if(mousePressed) {
					Point p = MouseInfo.getPointerInfo().getLocation();
					didMouseDragged(p.x, p.y);
				}
			}
		};
		ac.out.addDependent(mousePoller);
	}
	
	public void mouseDragged()
	{
		didMouseDragged(mouseX, mouseY);
	}

	
	int count = 0;
	long previousTime = 0;
	
	public void didMouseDragged(int mouseX, int mouseY)
	{
		float nx = mouseXToWorldX(mouseX);
		float ny = mouseYToWorldY(mouseY);
		
		// notify surface
		// cs.mouseMoved(ox,oy,nx,ny);
		surface.playerMoved(sp,ox,oy,nx,ny);
		
		// update old position
		ox = nx;
		oy = ny;
		
		long newTime = System.currentTimeMillis();
//		System.out.println("drag " + count++ + " " + (int)(newTime - previousTime));
		previousTime = newTime;
	}
	
	public void mouseReleased()
	{
		float nx = mouseXToWorldX(mouseX);
		float ny = mouseYToWorldY(mouseY);
		surface.playerReleased(sp,nx,ny);		
		ox = nx;
		oy = ny;
	}
	
	public void mousePressed()
	{
		float nx = mouseXToWorldX(mouseX);
		float ny = mouseYToWorldY(mouseY);
		surface.playerPressed(sp,nx,ny);
		ox = nx;
		oy = ny;
	}
	
	
	public float mouseXToWorldX(int x)
	{
		return (float) (1.0*x/width);
	}
	
	public float mouseYToWorldY(int y)
	{
		return (float) (1.0*y/height);
	}
}
