import java.awt.BorderLayout;
import java.io.IOException;
import java.util.Arrays;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.beads.data.AudioFile;
import net.beadsproject.beads.data.Sample;


public class SampleSeekTest {

	static class BufferedSamplePlayer extends UGen implements ChangeListener
	{
		Sample bs;
		int frame = 0;
		JSlider slider;
		
		// read one frame at a time from sample? or a whole chunk?
		static final boolean PERFRAME = true; 
		
		public BufferedSamplePlayer(AudioContext ac, Sample bs)
		{
			super(ac,bs.getNumChannels());
			this.bs = bs;	
			slider = null;
		}
		
		@Override
		public void calculateBuffer()
		{
			long nFrames = bs.getNumFrames();
			if (nFrames==AudioSystem.NOT_SPECIFIED)
			{
				System.out.println("dude it's an error");
				return;				
			}
			
			if (frame < nFrames)
			{
				if (PERFRAME)
				{
					int from = frame;
					int i = 0;
					int to = (int) Math.min(nFrames,frame+bufferSize);
					float[] data = new float[outs];
					for(;from<to;++from,++i)
					{
						bs.getFrame(from, data);
						for(int ch=0;ch<outs;ch++)
						{
							bufOut[ch][i] = data[ch];
						}
					}
				}
				else
				{				
					bs.getFrames(frame, bufOut);
				}
			}
			
			if ((nFrames - frame) < this.bufferSize)
			{
				for(int ch = 0;ch<this.outs;ch++)
					Arrays.fill(bufOut[ch], (int)(nFrames - frame), this.bufferSize, 0);					
				pause(true);
			}
			else
			{			
				frame += bufOut[0].length;
				slider.setValue(frame);
			}			
		}

		public void stateChanged(ChangeEvent e) {
			JSlider source = (JSlider)e.getSource();
		    //if (!source.getValueIsAdjusting()) {
		        int frame = (int)source.getValue();
		        this.frame = frame;
		        pause(false);
		    //}
		}
		
		public void setSlider(JSlider s)
		{
			this.slider = s;
		}
	}
	
	/**
	 * @param args
	 * @throws UnsupportedAudioFileException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException, UnsupportedAudioFileException {
		
		// String pathToFile = "../BeadsTests/audio/gammaBrosTheme.mp3.aif";
		String pathToFile = "../BeadsTests/audio/gammaBrosTheme.mp3";
		
		//FIXME problem with mp3s, 
		//example settings: TIMED, regionsize 100, lookahead 2000, lookback 2000, memory 5000.
		
		AudioContext ac = new AudioContext();
		Sample.Regime regime;
		//-------------------------
		//Sample buffering settings
		boolean total = false;
		if (total)
		{
			regime = Sample.Regime.newTotalRegime();
		}
		else
		{
			regime = new Sample.TimedRegime(1000,1000,0,2000,Sample.TimedRegime.Order.ORDERED);
		}
		
		//-------------------------
		AudioFile af = new AudioFile(pathToFile);
		af.trace = true; // trace access ops		
		

		final Sample samp = new Sample(af, regime);
					
		System.out.println(af.info());
		
		BufferedSamplePlayer bsp = new BufferedSamplePlayer(ac,samp);
		ac.out.addInput(bsp);
		
		//Create and set up the window.
        JFrame frame = new JFrame("BufferedSampleTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        assert samp.getNumFrames()>0;
        JSlider slider = new JSlider(0,(int) samp.getNumFrames());
        slider.addChangeListener(bsp);
        bsp.setSlider(slider);
        frame.add(slider, BorderLayout.CENTER);
        
        //Display the window.
        frame.pack();
        frame.setVisible(true);
		
		ac.start();
	}

}
