package main;

import com.softsynth.jsyn.EnvelopePlayer;
import com.softsynth.jsyn.Synth;

public class GrainStream extends Thread {
	
	WaveForm grain = new WaveForm();
//	double ampValStart;
//	double ampValEnd;
//	double ampJitStart;
//	double ampJitEnd;
//	
//	double soundDurValStart;
//	double soundDurValEnd;
//	double soundDurJitStart;
//	double soundDurJitEnd;
//	
//	double silenceDurValStart;
//	double silenceDurValEnd;
//	double silenceDurJitStart;
//	double silenceDurJitEnd;
	
	int startTick;
	int endTick;
	
	EnvelopePlayer envPlayer;
	
	PitchVector pitchVector;
	
	int instance;
	
	int noGrains;
	
	public GrainStream(){	
	}
	
	public void init(double aVS, double aVE, double aJS, double aJE, 
			double soDVS, double soDVE, double soDJS, double soDJE,
			double siDVS, double siDVE, double siDJS, double siDJE,
			PitchVector pV, int nG, int i){	
		
		//System.out.println("WOOHOO!!!");
		
//		ampValStart = aVS;
//		ampValEnd = aVE;
//		ampJitStart = aJS;
//		ampJitEnd = aJE;
//		
//		soundDurValStart = soDVS;
//		soundDurValEnd = soDVE;
//		soundDurJitStart = soDJS;
//		soundDurJitEnd = soDJE;
//		
//		//System.out.println(soundDurValStart);
//		
//		silenceDurValStart = siDVS;
//		silenceDurValEnd = siDVE;
//		silenceDurJitStart = siDJS;
//		silenceDurJitEnd = siDJE;
		
		pitchVector = pV;
		noGrains = nG;
		
		instance = i;
		
	}
	
	public void setStartTick(int sT){
		startTick = sT;
	}
	
	public void setEndTick(int eT){
		endTick = eT;
	}
	
	public void setTimer(EnvelopePlayer eP){
		envPlayer = eP;
	}
	
	public synchronized void run() {
		
		try {
			//System.out.println("waiting");
			this.wait(0);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		//boolean isOn = true;
		
		int startTime = startTick;
		int endTime = endTick;
		
		int advanceTime = (int) (Synth.getTickRate() * 0.5); // half second advance
		Synth.sleepUntilTick( startTime  - advanceTime /*(int) (Math.random() * 2 * Synth.getTickRate())*/);  // Wake up early!
		
		int upDuration = (int) (Synth.getTickRate() / 10);
		
		int nextTime = startTime;
		int nextGrainTime = startTime;
		
		while(true) 
		{
			if (Rise.IS_ENGINE_ON == true) {
				
				//System.out.println("IM ON!!!");
				
				//double freq = Math.random() * 300 + 300;
				if (Synth.getTickCount() > nextGrainTime - advanceTime) {
					
				double envPosition = envPlayer.output.get();
				
				int aPos = (int) (envPosition * (int) (Rise.TOTAL_DUR * 10));
				
				int rand = (int) (Math.random() * pitchVector.array[aPos].size());
				
				double randFadeJitter = (Math.random() * 5);
				
				//System.out.println(aPos + " " + pitchVector.array[aPos].size());
				
				double freq = (Double) pitchVector.array[aPos].get(rand);
				
//				double duration =
//						(soundDurValStart - envPosition * Math.abs(soundDurValStart - soundDurValEnd)) + 
//						((soundDurJitStart - envPosition * Math.abs(soundDurJitStart - soundDurJitEnd)) *
//						(Math.random() * 2 - 1));
//				grain.envRate.set(1./duration);
//				
//				double pause =
//					(silenceDurValStart - envPosition * Math.abs(silenceDurValStart - silenceDurValEnd)) + 
//					((silenceDurJitStart - envPosition * Math.abs(silenceDurJitStart - silenceDurJitEnd)) *
//					(Math.random() * 2 - 1));
//				
//				double amp =
//					((ampValStart + envPosition * Math.abs(ampValEnd - ampValStart)) + 
//				((ampJitStart + envPosition * Math.abs(ampJitEnd - ampJitStart)) *
//				(Math.random() * 2 - 1)));

				double duration =
					(Rise.GRAIN_SOUND_DUR_VAL_START - envPosition * Math.abs(Rise.GRAIN_SOUND_DUR_VAL_START - Rise.GRAIN_SOUND_DUR_VAL_END)) + 
					((Rise.GRAIN_SOUND_DUR_JIT_START - envPosition * Math.abs(Rise.GRAIN_SOUND_DUR_JIT_START - Rise.GRAIN_SOUND_DUR_JIT_END)) *
							(Math.random() * 2 - 1));
				grain.envRate.set(1./duration);

				double pause =
					(Rise.GRAIN_SILENCE_DUR_VAL_START - envPosition * Math.abs(Rise.GRAIN_SILENCE_DUR_VAL_START - Rise.GRAIN_SILENCE_DUR_VAL_END)) + 
					((Rise.GRAIN_SILENCE_DUR_JIT_START - envPosition * Math.abs(Rise.GRAIN_SILENCE_DUR_JIT_START - Rise.GRAIN_SILENCE_DUR_JIT_END)) *
							(Math.random() * 2 - 1));

				double amp =
					((Rise.GRAIN_AMP_VAL_START + envPosition * Math.abs(Rise.GRAIN_AMP_VAL_END - Rise.GRAIN_AMP_VAL_START)) + 
							((Rise.GRAIN_AMP_JIT_START + envPosition * Math.abs(Rise.GRAIN_AMP_JIT_END - Rise.GRAIN_AMP_JIT_START)) *
									(Math.random() * 2 - 1)));
				
				if (Synth.getTickCount() > endTime) {
					amp = amp * Math.abs((Synth.getTickCount() - endTime)/((Rise.FADE_DUR+randFadeJitter)*Synth.getTickRate())-1);
					if (Synth.getTickCount() > endTime + (Rise.FADE_DUR+randFadeJitter)*Synth.getTickRate()){
						amp = 0;
					}
				}
				
				//System.out.println((Synth.getTickCount() - endTime) + " " + amp + " " + (Synth.getTickCount() - endTime)/(Rise.FADE_DUR*Synth.getTickRate()));

				double spectrum =
					Rise.MIN_SPECTRUM + Math.random() * Math.abs(Rise.MAX_SPECTRUM - Rise.MIN_SPECTRUM);

				grain.spectrum.set(spectrum);
				grain.grainOn(0, freq, amp);

				//System.out.println("instance = " + instance);
				
				//System.out.println(duration + " " +  pause + " " + amp);
				
				int durationInTicks = (int) (Synth.getTickRate() * duration);
				int pauseInTicks = (int) (Synth.getTickRate() * pause);
				nextGrainTime += (durationInTicks + pauseInTicks);
				
				}
				nextTime += (upDuration);    // Advance nextTime by fixed amount.
				Synth.sleepUntilTick( nextTime - advanceTime );  // Wake up early!
			}
			else {
				try {
					//System.out.println("waiting");
					this.wait(0);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
