package zero1hd.rhythmbullet.audio.processor;

import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;

public class WAVAudioProcessor implements AudioProcessor {
	private boolean stereo;
	private int sampleRate;
	private byte[] buffer;
	private FileHandle fileHandle;
	private AudioInputStream audioInputStream;
	private long sampleFrames;
	
	public WAVAudioProcessor(FileHandle fileHandle) {
		this.fileHandle = fileHandle;
		AudioFormat format;
		try {
			audioInputStream = AudioSystem.getAudioInputStream(fileHandle.file());
			format = audioInputStream.getFormat();
			stereo = format.getChannels() > 1 ? true : false;
			sampleRate = (int) format.getSampleRate();
			sampleFrames = audioInputStream.getFrameLength();
		} catch (UnsupportedAudioFileException | IOException e) {
			Gdx.app.debug("WAVAudioProcessor", "Couldn't instantiate WAVAUdioProcessor due to error.");
			e.printStackTrace();
		}
		buffer = new byte[audioInputStream.getFormat().getFrameSize()];

	}
	
	public boolean isStereo() {
		return stereo;
	}
	
	public int getSampleRate() {
		return sampleRate;
	}
	
	@Override
	public int readSamples(short[] pcm) {
		int framesRead = 0;
		for (int sampleID = 0; sampleID < pcm.length; sampleID++) {
			try {
				if (audioInputStream.read(buffer) > 0) {
					pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
					if (stereo) {
						short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
						sampleID++;
						pcm[sampleID] = secondChan;
					}
					framesRead++;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		return framesRead;
	}
	
	@Override
	public int readFrames(float[] pcm) {
		int framesRead = 0;
		for (int sampleID = 0; sampleID < pcm.length; sampleID++) {
			try {
				if (audioInputStream.read(buffer) > 0) {
					pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
					if (stereo) {
						short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
						pcm[sampleID] = secondChan > pcm[sampleID] ? secondChan : pcm[sampleID];
					}
					framesRead++;
					pcm[sampleID] /= Short.MAX_VALUE+1;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		return framesRead;
	}
	
	@Override
	public FileHandle getMusicFileHandle() {
		return fileHandle;
	}
	
	@Override
	public long getSampleFrames() {
		return sampleFrames;
	}
	
	@Override
	public void dispose() {
		try {
			audioInputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}