package net.beadsproject.touch.examples;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.beads.data.Buffer;
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.Static;
import net.beadsproject.beads.ugens.WavePlayer;
import net.beadsproject.beads.ugens.SamplePlayer.EnvelopeType;
import net.beadsproject.beads.ugens.SamplePlayer.InterpolationType;
import net.beadsproject.touch.hardware.PQLabsTouchSurface;
import net.beadsproject.touch.hardware.TouchSurface;
import net.beadsproject.touch.hardware.TouchSurfaceListener;
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;
import PQSDKMultiTouch.PQMTClient;
import PQSDKMultiTouch.PQMTClientConstant;
import PQSDKMultiTouch.TouchClientRequest;
import PQSDKMultiTouch.TouchPoint;

public class PianoPQ extends PApplet {
	
	public static class PianoRegion extends Region {
		public Sample s;
		public PianoRegion(Sample s)
		{
			this.s = s;
		}
	}
	
	public static class PianoPlayer
	{
		public PianoRegion region;
		
		public void setRegion(PianoRegion pr)
		{
			region = 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 implements TouchSurfaceListener
	{
		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, 12);
			Gain g = new Gain(ac,2,new Static(ac,4.0f));
			ac.out.addInput(g);
			g.addInput(p);
			PianoWorld.g = p;
							
			String noteDir = "../audio/piano";
			Sample[] sampleList = new Sample[12];
			//add notes, one octave at mid register
			SampleManager.setBufferingRegime(Sample.Regime.newTotalRegime());
			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 List<Region> getRegions() {
			// TODO Auto-generated method stub
			return null;
		}
		
		@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));
			}			
		}
		
		public void contactMoved(int ID, int x, int y) {
			PianoPlayer pp = players.get(ID);
			Region r = regionMap.get(x,y);
			if (pp!=null && r!=null && r!=pp.region)
			{
				pp.setRegion((PianoRegion)(r));
			}			
		}

		@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);
		}		
		
		public void newContact(int ID, int x, int y) {
			// generate a new guy and play a sound
			Region r = regionMap.get(x,y);
			if (r!=null)
			{
				PianoPlayer pp = new PianoPlayer();
				pp.setRegion((PianoRegion)(r));	
				players.put(ID,pp);
			}
		}

		@Override
		public void moved(int id, int x, int y) {
			contactMoved(id,x,y);
		}

		@Override
		public void pressed(int id, int x, int y) {
			newContact(id,x,y);		
		}

		@Override
		public void released(int id) {
			contactEnded(id);			
		}
	}
	
	TouchSurface touchSurface;
	PianoWorld world;
	
	public void setup()
	{		
		size(screen.width,screen.height);
		noCursor();
		
		AudioContext ac = new AudioContext();
		world = new PianoWorld(this,ac,width,height);
		
		touchSurface = new PQLabsTouchSurface();
		touchSurface.setListener(world);
		touchSurface.start();
		
		ac.start();
	}
		
	public void draw()
	{	
		background(0);
		noFill();
		image(world.displayImage,0,0);
	}
}
