package electrosphere.audio;

import org.joml.Vector3f;
import org.lwjgl.openal.AL11;

import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;

import org.lwjgl.openal.AL10;

/**
 * A source of audio in the aural space
 */
public class AudioSource {
    
    //The id for the source
    int sourceId;
    
    /**
     * Creates an audio source object
     * @param loop if true, will loop audio, otherwise will not
     */
    protected static AudioSource create(boolean loop){
        AudioSource rVal = new AudioSource();
        rVal.sourceId = AL10.alGenSources();
        Globals.audioEngine.checkError();
        if(loop){
            AL10.alSourcei(rVal.sourceId, AL10.AL_LOOPING, AL10.AL_TRUE);
            Globals.audioEngine.checkError();
        }
        return rVal;
    }
    
    /**
     * Sets the buffer that this source pulls from
     * @param bufferId The id of the buffer
     */
    public void setBuffer(int bufferId) {
        stop();
        AL10.alSourcei(sourceId, AL10.AL_BUFFER, bufferId);
        Globals.audioEngine.checkError();
    }

    /**
     * Sets the position of the audio source
     * @param position the position
     */
    public void setPosition(Vector3f position) {
        AL10.alSource3f(sourceId, AL10.AL_POSITION, position.x, position.y, position.z);
        Globals.audioEngine.checkError();
    }

    /**
     * Sets the speed of the audio source
     * @param speed the speed
     */
    public void setSpeed(Vector3f speed) {
        AL10.alSource3f(sourceId, AL10.AL_VELOCITY, speed.x, speed.y, speed.z);
        Globals.audioEngine.checkError();
    }

    /**
     * Sets the temporal offset of the source (ie how far into the clip to start playingf)
     * @param time The time in seconds
     */
    public void setOffset(float time){
        AL10.alSourcef(sourceId, AL11.AL_SEC_OFFSET, time);
        Globals.audioEngine.checkError();
    }

    /**
     * Sets the gain of the audio source
     * @param gain the gain
     */
    public void setGain(float gain) {
        LoggerInterface.loggerAudio.DEBUG("Set Gain: " + gain);
        AL10.alSourcef(sourceId, AL10.AL_GAIN, gain);
        Globals.audioEngine.checkError();
    }

    /**
     * Sets an arbitrary property on the audio source
     * @param param The param flag
     * @param value The value to set the param to
     */
    public void setProperty(int param, float value) {
        AL10.alSourcef(sourceId, param, value);
        Globals.audioEngine.checkError();
    }

    /**
     * Plays the audio source
     */
    public void play() {
        AL10.alSourcePlay(sourceId);
        Globals.audioEngine.checkError();
    }

    /**
     * Gets whether the audio source is currently playing or not
     * @return True if it is playing, false otherwise
     */
    public boolean isPlaying() {
        boolean isPlaying = AL10.alGetSourcei(sourceId, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING;
        Globals.audioEngine.checkError();
        return isPlaying;
    }

    /**
     * Pauses the audio source
     */
    public void pause() {
        AL10.alSourcePause(sourceId);
        Globals.audioEngine.checkError();
    }

    /**
     * Stops the audio source
     */
    public void stop() {
        AL10.alSourceStop(sourceId);
        Globals.audioEngine.checkError();
    }

    /**
     * Cleans up the source
     */
    public void cleanup() {
        stop();
        AL10.alDeleteSources(sourceId);
        Globals.audioEngine.checkError();
    }
}
