package net.beadsproject.touch.examples;
import java.awt.Color;
import java.util.HashMap;
import java.util.List;

import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.beads.data.Pitch;
import net.beadsproject.beads.data.Sample;
import net.beadsproject.beads.data.SampleManager;
import net.beadsproject.beads.events.KillTrigger;
import net.beadsproject.beads.ugens.Envelope;
import net.beadsproject.beads.ugens.Gain;
import net.beadsproject.beads.ugens.PolyLimit;
import net.beadsproject.beads.ugens.SamplePlayer;
import net.beadsproject.beads.ugens.SamplePlayer.EnvelopeType;
import net.beadsproject.beads.ugens.SamplePlayer.InterpolationType;
import net.beadsproject.touch.world.Region;
import net.beadsproject.touch.world.RegionMap;
import net.beadsproject.touch.world.World;
import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;

/**
 * Piano example.
 * 
 * @author ben
 *
 */
public class PianoDemo extends PApplet {	
	
	public static class PianoRegion extends Region {
		public Sample s;
		public PianoRegion(Sample s)
		{
			this.s = s;
		}
	}
	
	public static class PianoPlayer
	{
		public void setRegion(PianoRegion pr)
		{
			if (pr==null) return;
			SamplePlayer sp = new SamplePlayer(PianoWorld.ac,pr.s);
			sp.setEnvelopeType(EnvelopeType.COARSE);
			sp.setInterpolationType(InterpolationType.NONE);
			sp.setKillOnEnd(true);
			
			Envelope env = new Envelope(PianoWorld.ac, 1f);
			Gain g = new Gain(PianoWorld.ac, 2, env);
			g.addInput(sp);
			env.addSegment(0f, 1000f, new KillTrigger(g));
			
			PianoWorld.g.addInput(g);
		}
	}
	
	public static class PianoWorld extends World
	{
		public static UGen g;
		public static AudioContext ac;
		
		public int width, height;
		
		public RegionMap regionMap;		
		public PImage displayImage;
		
		private HashMap<Integer,PianoPlayer> players;
		
		public PianoWorld(final PApplet app, final AudioContext ac, int w, int h)
		{
			PianoWorld.ac = ac;
			width = w;
			height = h;
			players = new HashMap<Integer,PianoPlayer>();
			
			//set up connection point
			PolyLimit p = new PolyLimit(ac, 2, 16);
			ac.out.addInput(p);
			PianoWorld.g = p;
							
			String noteDir = "../audio/piano";
			Sample[] sampleList = new Sample[12];
			//add notes, one octave at mid register
			for(int i = 0; i < 12; i++) {
				sampleList[i] = SampleManager.sample(noteDir + "/" + "Piano.mf." + Pitch.pitchNames[i] + "5" + ".wav");
			}
			SampleManager.group("piano", sampleList);
			
			// Generate regions and visual representation
			PianoRegion[] regions = new PianoRegion[12];
			HashMap<Region,Color> regionColours = new HashMap<Region,Color>();
			
			regionMap = new RegionMap(width,height);
			PGraphics img = app.createGraphics(width,height,P2D);
			img.beginDraw();
			img.background(0);
			img.noStroke();
			
			float dw = width/12.f;
			for(int i=0; i<12; i++)
			{
				// we divide the space vertically
				regions[i] = new PianoRegion(sampleList[i]);
				regionColours.put(regions[i], new Color(Color.HSBtoRGB((float) Math.random(), .75f, .75f)));
				
				RegionMap.PSetFill(img, i);
				img.rect(i*dw,0,dw,height);
			}			
			img.endDraw();
			
			regionMap.generateFromPGraphics(img, regions);
			displayImage = regionMap.generatePImage(app, regionColours);			
		}
		
		@Override
		public void contactEnded(int ID) {
			// TODO Auto-generated method stub
			players.remove(ID);
		}

		@Override
		public void contactMoved(int ID, Region dest) {
			PianoPlayer pp = players.get(ID);
			if (pp!=null)
			{
				pp.setRegion((PianoRegion)(dest));
			}			
		}

		@Override
		public List<Region> getRegions() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public void newContact(int ID, Region region) {
			// generate a new guy and play a sound
			PianoPlayer pp = new PianoPlayer();
			pp.setRegion((PianoRegion)(region));	
			players.put(ID,pp);
		}		
	}
	
	PianoWorld world;	
			
	public void setup()
	{		
		size(400,300);
		
		AudioContext ac = new AudioContext();
		world = new PianoWorld(this,ac,width,height);
		ac.start();		
	}
		
	public void draw()
	{	
		background(0);
		noFill();
		image(world.displayImage,0,0);
	}	
		
	public void mousePressed()
	{		
		Region r = world.regionMap.get(mouseX,mouseY);
		if (r!=null)
		{
			world.newContact(0,r);
			world.newContact(1,world.regionMap.get(width-mouseX,mouseY));
		}
	}
	
	public void mouseReleased()
	{
		world.contactEnded(0);
		world.contactEnded(1);		
	}
	
	public void mouseDragged()
	{
		Region r = world.regionMap.get(mouseX,mouseY);
		if (r!=null)
		{
			world.contactMoved(0, r);
			world.contactMoved(1, world.regionMap.get(width-mouseX,mouseY));
		}
	}
}
