package turgen.generator;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.SourceDataLine;
import turgen.Utils;


public class AudioSignalWriter implements SignalWriter {

    protected SourceDataLine line;
    protected final AudioFormat audioFormat;
    protected final int bufferSize;
    private int terminationSignalCounter;
    private byte[] terminationSignal;
    
    
    public AudioSignalWriter(int bitsPerSample,int channels,boolean signed,int bufferSize) {
        this.bufferSize=bufferSize;
        audioFormat = new AudioFormat((float) 44100, bitsPerSample, channels, signed, false);
        terminationSignalCounter=-1;
        terminationSignal=null;
    }
    
    
    public String prepare(String outputFile ) {
        /*Try to initialize sound card*/
        try {
            
            Line.Info desiredInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
            line = (SourceDataLine) AudioSystem.getLine(desiredInfo);
            line.open(audioFormat, bufferSize);
            line.start();
            
        } catch (Exception e) {
            return Utils.getTitledExceptionMessage("Unable to initialize sound card",e);
        }
        
        return null;
    }

    public void writeInitialSignal(byte[] signal) throws Exception {
        write(signal);
    }

    public boolean writeTerminationSignal() throws Exception {
        if (terminationSignal==null || terminationSignalCounter<1) return false;
        write(terminationSignal);
        terminationSignalCounter--;
        return true;
    }

    public void write(byte[] signal) throws Exception {
        line.write(signal, 0, signal.length);
    }

    public void prepareForClose() throws Exception {
        line.drain();
        line.stop();
    }

    public void close() throws Exception {
        line.close();
    }
    
    public void flush() throws Exception {
        line.drain();
    }

    public void prepareForTerminationSignal(byte[] signal) {
        if (signal==null) return;
        if (signal.length==0) {
            terminationSignalCounter=0;
        }
        else {
            terminationSignalCounter = (bufferSize/signal.length)+1;
        }
        terminationSignal=signal;
    }

}
