package de.rico.adventure.actions.custom;

import javax.media.opengl.GL;

import de.rico.adventure.actions.AbstractAction;
import de.rico.adventure.actions.ActionScheduler;
import de.rico.adventure.conversation.Sentence;
import de.rico.adventure.enums.State;
import de.rico.adventure.structure.StateManager;
import de.rico.engine.camera.Camera;
import de.rico.engine.effect.ortho.TextAreaRenderer;
import de.rico.engine.enums.Font;
import de.rico.engine.material.Color4f;

/**
 * This class is a game action to put a sentence that gets said by
 * a character in the queue.
 * @author Frank Bruns
 */
public class Say extends AbstractAction
{
	private TextAreaRenderer textAreaRenderer = null;
	private Sentence sentence = null;
	private boolean soundStarted = false;
	private int duration = 0; // duration of display
	private long cumulatedTime = 0L;
	private State backupState = null;

	/**
	 * Creates a new game action to say the specified text.
	 * @param s Sentence object to display
	 */
	public Say( Sentence s)
	{
		super(s.getCharacter());

		this.textAreaRenderer = new TextAreaRenderer(
				0,
				0,
				Camera.getInstance().getViewPort().getWidth(),
				10,
				10,
				new Color4f(1f,1f,1f,1f),
				new Color4f(0f,0f,0f,0.65f));

		this.textAreaRenderer.getTextRenderer().setFont(Font.HELVETICA_18);
		this.textAreaRenderer.setText(this.getEntity().getScreenName()+":   \""+s.getText()+"\"");

		this.sentence = s;

		// calculate the duration on a per letter basis
		this.duration = s.getText().length() * 100; // in miliseconds
	}

	/* (non-Javadoc)
	 * @see de.rico.adventure.actions.AbstractAction#finishUp()
	 */
	@Override
	public void finishUp()
	{
		// restore original state
		StateManager.getInstance().setState(this.backupState);

		this.textAreaRenderer.setText(null);
		this.textAreaRenderer = null;
		if(this.sentence.getSound() != null)
		{
			this.sentence.getSound().stop();
			
			// reload the sound file to be able to play it again later on 
			this.sentence.reloadSound();
		}
	}

	/* (non-Javadoc)
	 * @see de.rico.adventure.actions.AbstractAction#update(long)
	 */
	@Override
	public void update(long elapsedTime)
	{
		this.cumulatedTime += elapsedTime;

		// save original game state
		if(this.backupState == null)
			this.backupState = StateManager.getInstance().getState();

		// set to talk stat, if not in cinematic mode at teh moment
		if(this.backupState != State.CINEMATIC
				&& this.backupState != State.NO_INPUT_CINEMATIC)
		StateManager.getInstance().setState(State.TALK);

		if(this.sentence.getSound() != null)
		{
			// start sound, if not yet started
			if(this.soundStarted == false)
			{
				this.sentence.getSound().play();
				this.soundStarted = true;
			}

			// if the sound finished playing, remove the game action
			// from the queue
			if(this.sentence.getSound().hasFinished() == true)
			{
				// restore original state and remove the action from the scheduler
				StateManager.getInstance().setState(this.backupState);

				ActionScheduler.getInstance().removeFirst();
			}
		}
		// if no sound was assignd, remove the game action after
		// the before calculated amount of time
		else if(this.cumulatedTime >= this.duration)
		{
			// restore original state and remove the action from the scheduler
			StateManager.getInstance().setState(this.backupState);
			ActionScheduler.getInstance().removeFirst();
		}

	}

	/* (non-Javadoc)
	 * @see de.rico.adventure.actions.AbstractAction#draw(javax.media.opengl.GL)
	 */
	@Override
	public void draw(GL gl)
	{
		if(this.textAreaRenderer != null)
			this.textAreaRenderer.draw();
	}
}
