package kr;

import java.io.File;

import javax.swing.SwingUtilities;

import kr.gui.GuiUtils;
import kr.util.ListenerManager;
import kr.util.audio.AudioClip;
import kr.util.audio.SubtractedBkgAudioClip;
import kr.util.sample.SampleManager;

/**
 * Contains sampled audio aspects of the app
 */
public class AudioModel {
	private AudioChannelModel bkgChannel, vocalsChannel;
	private SampleManager sm = new SampleManager();
	private File bkgFile;
	private File vocalsFile;
	private boolean deriveBackgroundFromVocalsFlag;

	public enum MessageType { BKG_CLIP_UPDATED, VOCALS_CLIP_UPDATED, EFFECT_FLAGS_UPDATED };

	public AudioModel() {
		bkgChannel = new AudioChannelModel();
		vocalsChannel = new AudioChannelModel();
	}

	public AudioChannelModel getBkgChannel() {
		return bkgChannel;
	}

	public AudioChannelModel getVocalsChannel() {
		return vocalsChannel;
	}

	
	public void setBkgClip(AudioClip bkgClip) {
		this.bkgChannel.setClip(bkgClip);
		
		ListenerManager.inst().notifyGui(this, MessageType.BKG_CLIP_UPDATED);
	}

	public void setVocalsClip(AudioClip vocalsClip) {
		this.vocalsChannel.setClip(vocalsClip);
		ListenerManager.inst().notifyGui(this, MessageType.VOCALS_CLIP_UPDATED);
	}

	public void setBkgFile(final File bkgFile) {
		if(bkgFile != null)
			GuiUtils.invokeInNonAwtThread(new Runnable() { public void run () { setBkgClip(sm.getData(bkgFile));}});
		else setBkgClip(null);
		this.bkgFile = bkgFile;
		setDeriveBackgroundFromVocalsFlag(false);
	}

	public void setVocalsFile(final File vocalsFile) {
		if(vocalsFile != null)
			GuiUtils.invokeInNonAwtThread(new Runnable() { public void run () { setVocalsClip(sm.getData(vocalsFile));}});
		else setVocalsClip(null);

		this.vocalsFile = vocalsFile;
	}

	public int getMaxMilliSeconds() {
		int maxMicros = 0;
		if(bkgChannel.getClip() != null)
			maxMicros = bkgChannel.getClip().getMaxMicros();
		if(vocalsChannel.getClip() != null)
			maxMicros = Math.max(maxMicros, vocalsChannel.getClip().getMaxMicros());
		
		return maxMicros/1000;
	}

	public File getBkgFile() {
		return bkgFile;
	}

	public File getVocalsFile() {
		return vocalsFile;
	}

	public void setDeriveBackgroundFromVocalsFlag(boolean deriveBackgroundFromVocalsFlag) {
		if(this.deriveBackgroundFromVocalsFlag == deriveBackgroundFromVocalsFlag)
			return;
		
		this.deriveBackgroundFromVocalsFlag = deriveBackgroundFromVocalsFlag;
		if(deriveBackgroundFromVocalsFlag)
			bkgChannel.deriveFrom(new SubtractedBkgAudioClip(), vocalsChannel);
		else
			bkgChannel.doNotDerive();

		ListenerManager.inst().notifyGui(this, MessageType.BKG_CLIP_UPDATED);
		ListenerManager.inst().notifyGui(this, MessageType.EFFECT_FLAGS_UPDATED);
	}
	
	public boolean isDeriveBackgroundFromVocalsFlag() {
		return deriveBackgroundFromVocalsFlag;
	}

}

class AudioModelTest {
	public static void main(String[] argv) throws Exception {
		AudioModel m = new AudioModel();
	}
}
 /*
public void loadAudioFile(File file) throws IOException, UnsupportedPlugInException, NotConfiguredError, NoDataSinkException, NotRealizedError, InterruptedException, NoPlayerException {
Processor proc = null;
MediaLocator ml = new MediaLocator(file.toURL());
proc = Manager.createProcessor(ml);

JMFUtil.configure(proc);
ContentDescriptor[] contentDescriptors = proc
		.getSupportedContentDescriptors();

proc.setContentDescriptor( 
           new ContentDescriptor( ContentDescriptor.RAW));

TrackControl[] trackControls = proc.getTrackControls();
Control [] controls = proc.getControls();

/*Panel p = null;

for(Control c : controls)
{
	if(c instanceof Panel)
		p = (Panel)c;
}/

//trackControls[0].setRenderer(new AudioModelRenderer());
Renderer r;
//trackControls[0].setRenderer(r=new JavaSoundRenderer());

JMFUtil.realize(proc);
/*JFrame f = new JFrame();
Container fp = f.getContentPane();
fp.setLayout(new GridBagLayout());*/

/*GridBagConstraints c = new GridBagConstraints();
c.weightx = 1; 
c.weighty = 1;
c.fill = c.BOTH;
fp.add(proc.getControlPanelComponent(), c);

Component cc = proc.getControlPanelComponent();

//f.setContentPane(proc.getControlPanelComponent());
f.pack();
f.setVisible(true);/

//proc.setContentDescriptor(null);
//JMFUtil.start(proc);
//System.out.println("started the piece of shit");



PushBufferDataSource ds = (PushBufferDataSource)proc.getDataOutput();
//Player pl = Manager.createPlayer(ds);
JMFUtil.start(proc);
//pl.start();

/*while(true)
{

pl.start();
System.out.println("started the piece of shit");
Thread.sleep(5000);
//JMFUtil.stop(proc);
pl.stop();
System.out.println("stopped the piece of shit");
Thread.sleep(3000);
	
//pl.setMediaTime(new Time(Math.random() * 160.));
}/

TrackControl track[] = proc.getTrackControls();

boolean encodingOk = false;


/*for (int i = 0; i < track.length; i++) { 
    if (!encodingOk && track[i] instanceof FormatControl) { 

        if (((FormatControl)track[i]).
            setFormat( new AudioFormat(AudioFormat.ALAW, 
                                       48000, 
               		               8, 
                   		       2)) == null) {

            track[i].setEnabled(false); 
        }
        else {
            encodingOk = true; 
        }
    } else { 
        // we could not set this track to gsm, so disable it 
        track[i].setEnabled(false); 
    } ds instanceof javax.media.protocol.PushBufferDataSource
}

MediaLocator m = new MediaLocator("file://home/tim/foo.wav");
DataSink d = Manager.createDataSink(ds, m);

d.open();
d.start(); 


/*PushBufferStream [] pbss = ds.getStreams();

PushBufferStream pbs = pbss[0];

Buffer b;
ByteBuffer d = new ByteBuffer();
while(true)
{
	pbs.read(b=new Buffer());
	System.out.println("read "+b);
	if(b.getData() == null) break;
	d.append((byte [])b.getData());
}


		ByteArrayInputStream s = new ByteArrayInputStream(d.getBytes());


javax.sound.sampled.AudioFormat shittyShit = new javax.sound.sampled.AudioFormat(
		javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED,)
AudioInputStream ais = new AudioInputStream((InputStream)s,(AudioFormat)pbs.getFormat(),(long)d.length());*/


/*PushBufferStream [] pbss = ds.getStreams();

PushBufferStream pbs = pbss[0];

Buffer b;
pbs.read(b=new Buffer());*/


/*DataSink sink;
MediaLocator dest = new MediaLocator(new File("/home/tim/foo.dat")
		.toURL());
sink = Manager.createDataSink(proc.getDataOutput(), dest);
sink.open();
sink.start();


}

private static class AudioModelRenderer implements Renderer {
private static Format[] formats = new Format[] { new AudioFormat(
		AudioFormat.LINEAR) };

public AudioModelRenderer() {
}

public Format[] getSupportedInputFormats() {
	return formats;
}

public Format setInputFormat(Format format) {
	return formats[0];
}

public void start() {
}

public void stop() {
}

public int process(Buffer buffer) {
	System.out.println("process " + buffer);
	return BUFFER_PROCESSED_OK;
}

public String getName() {
	return "the funny audio model plugin, ha ha";
}

public void open() throws ResourceUnavailableException {
}

public void close() {
}

public void reset() {
}

public Object[] getControls() {
	// TODO Auto-generated method stub
	return null;
}

public Object getControl(String controlType) {
	return null;
}
}
*/