package simogl.effect.fog;

import javax.media.opengl.GL;

/**
 * This class can be used to represent fog
 * @author Frank Bruns
 *
 */
public class Fog
{
	boolean enabled = false;
	boolean linearMode = false;
	boolean expMode = true;
	boolean exp2Mode = false;
	
	float[] color = {1f,1f,1f,1f};
	float start = 0.0f;
	float end = 1.0f;
	float density = 0.005f;
	
	/**
	 * Creates a new Fog object with the following default properties:
	 * <br>
	 * <ul>
	 * 	<li><b>Fog mode: </b>EXP</li>
	 * 	<li><b>Color: </b>RGBA parameters all 1.0f (pure white fog)</li>
	 * 	<li><b>Density: </b>1.0f</li>
	 * 	<li><b>Start/End: </b> 0.0f/1.0f</li>
	 * </ul>
	 * Remember to enable the use of fog with the setEnabled()-method,
	 * because it is disabled by default 
	 *
	 */
	public Fog()
	{
		
	}
	
	/**
	 * Creates a new Fog object with the specified parameters. Usually at most 
	 * one Fog object of this type is needed in the whole application.
	 * <br>
	 * Remember to enable the use of fog with the setEnabled()-method,
	 * because it is disabled by default
	 * @param red amount of red
	 * @param green amount of green
	 * @param blue amount of blue
	 * @param alpha alpha value
	 * @param start start position of the fog
	 * @param end end position of the fog
	 */
	public Fog(float red, float green, float blue, float alpha, float start, float end)
	{
		this.color[0] = red;
		this.color[1] = green;
		this.color[2] = blue;
		this.color[3] = alpha;
		
		this.start = start;
		this.end = end;
	}
	
	/**
	 * Sets the RGBA color of the fog to the specified values
	 * @param red amount of red
	 * @param green amount of green
	 * @param blue amount of blue
	 * @param alpha alpha value
	 */
	public void setColor(float red, float green, float blue, float alpha)
	{
		this.color[0] = red;
		this.color[1] = green;
		this.color[2] = blue;
		this.color[3] = alpha;
	}
	
	/**
	 * Returns the RGBA color of the fog as an array of four values
	 * @return RGBA color of the fog
	 */
	public float[] getColor()
	{
		return this.color;
	}
	
	/**
	 * Specifies whether the fog shall be enabled or disabled.
	 * @param enableFog enable fog? --> true = yes, false = no
	 */
	public void setEnabled(boolean enableFog)
	{
		this.enabled = enableFog;
	}
	
	/**
	 * Sets the start position of the fog
	 * @param start fog's start position
	 */
	public void setStart(float start)
	{
		this.start = start;
	}
	
	/**
	 * Returns the fog's start position
	 * @return fog's start position
	 */
	public float getStart()
	{
		return this.start;
	}
	
	/**
	 * Sets the end position of the fog
	 * @param end the fog's end position
	 */
	public void setEnd(float end)
	{
		this.end = end;
	}
	
	/**
	 * Returns the end position of the fog
	 * @return the fog's end position
	 */
	public float getEnd()
	{
		return this.end;
	}
	
	/**
	 * Sets the start and end position of the fog
	 * @param start start position
	 * @param end end position
	 */
	public void setStartAndEnd(float start, float end)
	{
		this.start = start;
		this.end = end;
	}
	
	/**
	 * Sets the fog's density. The default value is 1.0f. Reasonable 
	 * values for linear fog mode are around 0.5f and around 0.005f for
	 * exp fog mode.
	 * @param density density value for the fog
	 */
	public void setDensity(int density)
	{
		this.density = density;
	}
	
	/**
	 * Returns the fog's density
	 * @return density value of the fog
	 */
	public float getDensity()
	{
		return this.density;
	}
	
	/**
	 * Sets the fog mode to linear fog mode. If you switch to this mode
	 * the fog density value is set to 0.5f, because it is a reasonable
	 * start value for it.
	 *
	 */
	public void setToLinearMode()
	{
		// Set the new density only, if application wasn't already in linear mode
		if(this.linearMode == false)this.density = 0.5f;
		this.linearMode = true;
		this.expMode = false;
		this.exp2Mode = false;
	}
	
	/**
	 * Returns whether linear fog mode is active
	 * @return is linear mode active? --> true = yes, false = no 
	 */
	public boolean isInLinearMode()
	{
		return this.linearMode;
	}
	
	
	/**
	 * Sets the fog mode to exp fog mode. This is the default fog
	 * mode. If you switch to this mode the fog density value is 
	 * set to 0.005f, because it is a reasonable start value for it.
	 *
	 */
	public void setToExpMode()
	{
		// Set the new density only, if application wasn't already in exp mode
		if(this.expMode == false)this.density = 0.005f;
		this.linearMode = false;
		this.expMode = true;
		this.exp2Mode = false;
	}
	
	/**
	 * Returns whether exp fog mode is active
	 * @return is exp mode active? --> true = yes, false = no 
	 */
	public boolean isInExpMode()
	{
		return this.expMode;
	}
	
	
	/**
	 * Sets the fog mode to exp2 fog mode. If you switch to this mode
	 * the fog density value is set to 0.005f, because it is 
	 * a reasonable start value for it.
	 *
	 */
	public void setToExp2Mode()
	{
		// Set the new density only, if application wasn't already in exp2 mode
		if(this.exp2Mode == false)this.density = 0.005f;
		this.linearMode = false;
		this.expMode = false;
		this.exp2Mode = true;
	}
	
	/**
	 * Returns whether exp2 fog mode is active
	 * @return is exp2 mode active? --> true = yes, false = no 
	 */
	public boolean isInExp2Mode()
	{
		return this.exp2Mode;
	}
	
	public void draw(GL gl)
	{
		if(this.enabled)
		{
			gl.glEnable(GL.GL_FOG);
			
			// activate correct fog mode
			if(this.linearMode) gl.glFogi(GL.GL_FOG_MODE, GL.GL_LINEAR);
			if(this.expMode) gl.glFogi(GL.GL_FOG_MODE, GL.GL_EXP);
			if(this.exp2Mode) gl.glFogi(GL.GL_FOG_MODE, GL.GL_EXP2);
			
			// adjust density
			gl.glFogf(GL.GL_FOG_DENSITY,this.density);
			
			// set fog color
			gl.glFogfv(GL.GL_FOG_COLOR,this.color,0);
			
			// set fog start and end
			gl.glFogf(GL.GL_FOG_START,this.start);
			gl.glFogf(GL.GL_FOG_END,this.end);			
		}
		else gl.glDisable(GL.GL_FOG);
	}
}
