// working_directory on android is "assets/" which makes SDL freak out.
function GetPathPrepend()
{
	if (os_type != os_android) return working_directory;
	else return "";
}

// StaticSounds are usually short and intended to be played multiple times.
// All of the sound data lives in memory for as long as the StaticSound exists.
// Playing a StaticSound returns a SoundInstance.
function LoadStaticSound(filename)
{
	var filePath = GetPathPrepend() + "audio/static/" + filename;
	var staticSoundID = FAudioGMS_StaticSound_LoadWAV(filePath);
	return new StaticSound(staticSoundID);
}

function StaticSound(_staticSoundID) constructor
{
	staticSoundID = _staticSoundID;

	// Create a sound instance from this static sound.
	static CreateSoundInstance = function()
	{
		var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
		var instance = new SoundInstance(instanceID);
		return instance;
	}

	// Plays and returns a sound instance!
	// MUST be destroyed when you aren't referencing it any more or you will leak memory!
	static Play = function(pan = 0, pitch = 1, volume = 1, loop = false, loopStartInMilliseconds = 0, loopEndInMilliseconds = 0)
	{
		var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
		var instance = new SoundInstance(instanceID);
		instance.SetLoop(loop);
		if (loop)
		{
			instance.SetPlayRegion(loopStartInMilliseconds, loopEndInMilliseconds);
		}
		instance.SetPan(pan);
		instance.SetPitch(pitch);
		instance.SetVolume(volume);
		instance.Play();
		return instance;
	}

	// Automatically destroys the SoundInstance when playback is finished.
	// Does NOT return an instance!
	static PlayOneOff = function(pan = 0, pitch = 1, volume = 1)
	{
		var instance = Play(pan, pitch, volume, false);
		instance.DestroyWhenFinished();
	}

	// Plays and returns a sound instance!
	// MUST be destroyed when you aren't referencing it any more or you will leak memory!
	static PlaySpatial = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1, loop = false)
	{
		var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
		var instance = new SoundInstance(instanceID);
		instance.SetLoop(loop);
		instance.Set3DPosition(xPosition, yPosition, zPosition);
		instance.SetPitch(pitch);
		instance.SetVolume(volume);
		instance.Play(loop);
		return instance;
	}

	// Automatically destroys the SoundInstance when playback is finished.
	// Does NOT return an instance!
	static PlaySpatialOneOff = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1)
	{
		var instance = PlaySpatial(xPosition, yPosition, zPosition, pitch, volume, false);
		instance.DestroyWhenFinished();
	}

	// Destroys the FAudioGMS static sound.
	// If you use the StaticSound after calling this function, you are going to have a bad time.
	// If you call this while there are still instances of the StaticSound, you are going to have a bad time.
	static Destroy = function()
	{
		FAudioGMS_StaticSound_Destroy(staticSoundID);
	}
}

// StreamingSounds are longer and usually only one copy is played at a time.
// The audio is streamed off the disk, so only a small amount of memory is used at a time.
// Good for things like music or voiceover playback.
// Note that StreamingSounds are SoundInstances.
function LoadStreamingSound(filename)
{
	var filePath = GetPathPrepend() + "audio/streaming/" + filename;
	soundInstanceID = FAudioGMS_StreamingSound_LoadOGG(filePath);
	return new SoundInstance(soundInstanceID);
}

function SoundInstance(_soundInstanceID) constructor
{
	soundInstanceID = _soundInstanceID;

	// Plays the sound or resumes from pause.
	static Play = function()
	{
		FAudioGMS_SoundInstance_Play(soundInstanceID);
	}

	// Pauses playback.
	static Pause = function()
	{
		FAudioGMS_SoundInstance_Pause(soundInstanceID);
	}

	// Stops playback completely. If Play is called it will resume from the beginning of the sound.
	static Stop = function()
	{
		FAudioGMS_SoundInstance_Stop(soundInstanceID);
	}

	// Sets the 3-dimensional position of the sound. You probably want to use SetListenerPosition too.
	static Set3DPosition = function(xPosition, yPosition, zPosition)
	{
		FAudioGMS_SoundInstance_Set3DPosition(soundInstanceID, xPosition, yPosition, zPosition);
	}

	// Sets the 3-dimensional velocity of the sound. You probably want to use SetListenerVelocity too.
	static Set3DVelocity = function(xVelocity, yVelocity, zVelocity)
	{
		FAudioGMS_SoundInstance_Set3DVelocity(soundInstanceID, xVelocity, yVelocity, zVelocity);
	}

	// Sets whether the sound instance loops (true) or does not (false).
	static SetLoop = function(loop)
	{
		FAudioGMS_SoundInstance_SetLoop(soundInstanceID, loop);
	}

	// Sets the panning value of the sound. -1 is farthest left, 1 is farthest right, 0 is center.
	// NOTE: This is ignored if you have called Set3DPosition.
	static SetPan = function(pan)
	{
		FAudioGMS_SoundInstance_SetPan(soundInstanceID, pan);
	}

	// Sets the pitch of the sound. Default is 1. Lower than 1 is pitched down, higher than 1 is pitched up.
	static SetPitch = function(pitch)
	{
		FAudioGMS_SoundInstance_SetPitch(soundInstanceID, pitch);
	}

	// Sets the volume of the sound. Default is 1. Lower than 1 is quieter, greater than 1 is louder.
	// If you set the milliseconds value then this will fade over time.
	static SetVolume = function(volume, milliseconds = 0)
	{
		if (milliseconds > 0)
		{
			FAudioGMS_SoundInstance_SetVolumeOverTime(soundInstanceID, volume, milliseconds);
		}
		else
		{
			FAudioGMS_SoundInstance_SetVolume(soundInstanceID, volume);
		}
	}

	// Sets the position of track playback.
	static SetTrackPosition = function(seconds)
	{
		FAudioGMS_SoundInstance_SetTrackPositionInSeconds(soundInstanceID, seconds);
	}

	// Sets the playback region for the sound instance.
	static SetPlayRegion = function(loopStartInMilliseconds, loopEndInMilliseconds)
	{
		FAudioGMS_SoundInstance_SetPlayRegion(soundInstanceID, loopStartInMilliseconds, loopEndInMilliseconds);
	}

	// Sets a low pass filter on the sound.
	// frequency: 0.0 <-> 1.0. 1.0 means all sound gets through.
	// Q: set this to 1 unless you know what you're doing
	static SetLowPassFilter = function(frequency, Q = 1.0)
	{
		FAudioGMS_SoundInstance_SetLowPassFilter(soundInstanceID, frequency, Q);
	}

	// Sets a high pass filter on the sound.
	// frequency: 0.0 <-> 1.0. 0.0 means all sound gets through.
	// Q: set this to 1 unless you know what you're doing
	static SetHighPassFilter = function(frequency, Q = 1.0)
	{
		FAudioGMS_SoundInstance_SetHighPassFilter(soundInstanceID, frequency, Q);
	}

	// Sets a band pass filter ont he sound.
	// frequency: 0.0 <-> 1.0
	// Q: set this to 1 unless you know what you're doing
	static SetBandPassFilter = function(frequency, Q = 1.0)
	{
		FAudioGMS_SoundInstance_SetBandPassFilter(soundInstanceID, frequency, Q);
	}

	// Sets an effect chain on the sound.
	// Gain is how much the effect chain "affects" the sound. 1.0 is max.
	// NOTE: Any changes to the effect chain will NOT apply automatically after this is set!
	// You MUST call this function again if you want changed parameters to apply!
	static SetEffectChain = function(effectChain, gain)
	{
		FAudioGMS_SoundInstance_SetEffectChain(soundInstanceID, effectChain.effectChainID, gain);
	}

	// Sets the effect gain of the current effect chain.
	// Does nothing if no effect chain is set.
	static SetEffectGain = function(gain)
	{
		FAudioGMS_SoundInstance_SetEffectGain(soundInstanceID, gain);
	}

	static QueueSoundInstance = function(queueSoundInstance)
	{
			FAudioGMS_SoundInstance_QueueSoundInstance(soundInstanceID, queueSoundInstance.soundInstanceID);
	}

	// Gets the pitch of the sound.
	static GetPitch = function()
	{
		return FAudioGMS_SoundInstance_GetPitch(soundInstanceID);
	}

	// Gets the volume of the sound.
	static GetVolume = function()
	{
		return FAudioGMS_SoundInstance_GetVolume(soundInstanceID);
	}

	// Gets the total length of the track.
	static GetTrackLengthInSeconds = function()
	{
		return FAudioGMS_SoundInstance_GetTrackLengthInSeconds(soundInstanceID);
	}

	// Gets the current track position.
	static GetTrackPositionInSeconds = function()
	{
		return FAudioGMS_SoundInstance_GetTrackPositionInSeconds(soundInstanceID);
	}

	// Destroys the FAudioGMS sound instance.
	// If you use the SoundInstance after calling this you are going to have a bad time.
	static Destroy = function()
	{
		FAudioGMS_SoundInstance_Destroy(soundInstanceID);
	}

	// Sets the FAudioGMS sound instance to destroy itself when playback is done.
	// Calling this on a looping sound is not a good idea.
	// If you use the SoundInstance after calling this you might have a bad time.
	static DestroyWhenFinished = function()
	{
		FAudioGMS_SoundInstance_DestroyWhenFinished(soundInstanceID);
	}

	SetPan(0);
	SetPitch(1);
	SetVolume(1);
}

// Effect chains allow you to modify sound playback using audio effects.
// Right now only reverb is implemented, but more effects will probably come later.
function EffectChain() constructor
{
	effectChainID = FAudioGMS_EffectChain_Create();

	// Adds a reverb effect to the effect chain.
	static AddReverb = function(
		wetDryMix,
	    reflectionsDelay,
	    reverbDelay,
	    earlyDiffusion,
	    lateDiffusion,
	    lowEQGain,
	    lowEQCutoff,
	    highEQGain,
	    highEQCutoff,
	    reflectionsGain,
	    reverbGain,
	    decayTime,
	    density,
	    roomSize
	) {
		FAudioGMS_EffectChain_AddReverb(
			effectChainID,
			wetDryMix,
		    reflectionsDelay,
		    reverbDelay,
		    earlyDiffusion,
		    lateDiffusion,
		    lowEQGain,
		    lowEQCutoff,
		    highEQGain,
		    highEQCutoff,
		    reflectionsGain,
		    reverbGain,
		    decayTime,
		    density,
		    roomSize
		);
	}

	// Adds a default reverb effect to the effect chain.
	// This is a good place to start if you don't know what all the reverb params do.
	static AddDefaultReverb = function()
	{
		FAudioGMS_EffectChain_AddReverb(
			effectChainID,
			100,
			7,
			11,
			15,
			15,
			8,
			4,
			8,
			6,
			-26,
			10,
			1.49,
			100,
			100
		);
	}

	// Destroys the FAudioGMS effect chain.
	// If you use the EffectChain after calling this you are going to have a bad time.
	static Destroy = function()
	{
		FAudioGMS_EffectChain_Destroy(effectChainID);
	}
}

// Sets the position of the listener for 3D audio.
function SetListenerPosition(xPosition, yPosition, zPosition)
{
	FAudioGMS_SetListenerPosition(xPosition, yPosition, zPosition);
}

// Sets the velocity of the listener for 3D audio.
function SetListenerVelocity(xVelocity, yVelocity, zVelocity)
{
	FAudioGMS_SetListenerVelocity(xVelocity, yVelocity, zVelocity);
}

// Stops all audio playback.
function StopAllAudio()
{
	FAudioGMS_StopAll();
}