
// flash

// NME
import nme.display.Sprite;

import nme.display.Bitmap;
import nme.display.BitmapData;
import nme.display.GradientType;
import nme.display.Shape;

import nme.utils.Timer;
import nme.events.TimerEvent;

import nme.filters.BitmapFilterQuality;
import nme.filters.BlurFilter;

import nme.text.TextField;
import nme.text.TextFormat;
import nme.text.TextFieldAutoSize;
import nme.text.TextFieldType;

import nme.filters.GlowFilter;
import nme.geom.Matrix;
import nme.geom.Point;
import nme.geom.Rectangle;

import nme.Lib;


/**
 * Ajoute un effet de défilement sur du texte. 
 * Auteur : Matthieu
 * http://www.haxe-facile.com/
 * 
 */
class TextMove extends Sprite
{
	private var sTextInput : String;// le texte à afficher
	
	private var oTimer : Timer;// délai d'apparition de chaque lettre
	
	private var nIndex : Int;

	private var oContainerText : Sprite;// contient le texte défilant

	private var offset		: Float;	// Décalage en Y et variable d'incrementation propre à la lettre
	private var xStartPos	: Float;	// Position de départ de la lettre
	private var yStartPos	: Float;	// Position de départ de la lettre


	/**
	 * Constructeur.
	 * 
	 */
	public function new()
	{
		super();

		// appel toutes les 95 ms de la function sineLoop
		oTimer = new Timer(95);
		oTimer.addEventListener (TimerEvent.TIMER, onDefilTxt);
	}




	/**
	 * Affiche le texte petit à petit.
	 * Possibilité d'ajouter d'autres effets sur le texte.
	 * 
	 */
	private function onDefilTxt(event : TimerEvent) : Void
	{
		// création d'un bitmap à partir d'un caractère
		var sCharacter:String = sTextInput.substr( nIndex, 1 );
		var oContainerLetter = createEffect( sCharacter );
		
		// positionne le caractère
		oContainerLetter.y = yStartPos;
		oContainerLetter.x = xStartPos;
		oContainerLetter.scaleX = oContainerLetter.scaleY = 0.75 + Math.sin( offset ) * 0.33 * Math.random();
		oContainerText.addChild(oContainerLetter);// affiche le caractère

		xStartPos += oContainerLetter.width;
		nIndex++;// caractère suivant
		offset += 0.2 * Math.random();

		// une fois que la phrase est affichée entièrement, recommence l'affichage sur une autre ligne
		if (nIndex == sTextInput.length)
		{
			nIndex=0;
			yStartPos += oContainerLetter.height + 5;
			xStartPos = offset = 0;

			// si le texte dépasse de l'écran, stop l'affichage
			var fPos = yStartPos + this.y + oContainerLetter.height;
			if( fPos > Lib.current.stage.stageHeight )	oTimer.stop();
		}

	}
	
	
	/**
	 * Création d'un effet pour chaque caractère.  
	 * Convertit le caractère en bitmap avec un effet.
	 * 
	 * @return {[type]} [description]
	 */
	private function createEffect(char : String):Sprite
	{
		var oContainer = new Sprite();
		oContainerText.addChild(oContainer);

		// créé le champ de texte pour la lettre 
		var oTextfield = new TextField();
		oTextfield.selectable = false;
		oTextfield.text = char;
		oTextfield.autoSize = TextFieldAutoSize.LEFT;

		var oTextFormat = new TextFormat("Arial", 28 );
		oTextfield.setTextFormat( oTextFormat );

		// créé un carré dégradé de couleurs
		var oShape = new Shape();
		var oMatrix = new Matrix();
		oMatrix.createGradientBox( oTextfield.width, oTextfield.height, -Math.PI / 2 );
		oShape.graphics.beginGradientFill( GradientType.LINEAR, 
			[ 0x1100FF, 0xFF33C0, 0xFF2200 ], 
			[ 1, 1, 1 ], 
			[ 0, 128, 255 ], 
			oMatrix 					);
		oShape.graphics.drawRect( 0, 0, oTextfield.width, oTextfield.height );
		oShape.graphics.endFill();
		
		// créé un bitmap à partir du champ de texte de la lettre
		var oBitmapLetter = new BitmapData( Std.int ( oTextfield.width ), Std.int( oTextfield.height ), true, 0 );
		oBitmapLetter.draw( oTextfield );
		
		// créé un bitmap à partir du dégradé de couleurs
		var oBitmapDataColor = new BitmapData( Std.int ( oTextfield.width ), Std.int( oTextfield.height ), true, 0 );
		oBitmapDataColor.draw( oShape );
		var oBitmapColor = new Bitmap( oBitmapDataColor );
		
		// découpe le dégradé de couleurs en forme de la lettre
		oBitmapDataColor.copyChannel( oBitmapLetter, 
			new Rectangle( 0, 0, Std.int ( oTextfield.width ), Std.int( oTextfield.height ) ),
			new Point( 0, 0 ), 8, 8 );
		
		// libère la mémoire du bitmap qui ne sert plus à rien
		oBitmapLetter.dispose();
		
		// ajoute un contour noir à la lettre en couleur
		filters = [ new GlowFilter( 0, 1, 2, 2, 3, 3 ) ];
		
		oContainer.addChild( oBitmapColor );
		//oContainer.addChild(oTextfield);
		return oContainer;
	}



	/**
	 * Lance l'affichage du texte, lettre une par une.
	 * @param value : le texte à afficher.
	 * 
	 */
	public function startDefil(value:String):Void
	{
		sTextInput = value;
		nIndex = 0;
		offset = 0;
		xStartPos = yStartPos = 0;
		oTimer.start();

		if( oContainerText != null)	removeChild(oContainerText);
		oContainerText = new Sprite();
		addChild(oContainerText);
	}
	
	
	/**
	 * Arrête le défilement du texte.
	 * 
	 */
	public function stopDefil():Void
	{
		oTimer.stop();
	}
	
	
	
	/**
	 * Vitesse de défilement en ms.
	 * 
	 */
	public function setSpeed(value:Int) : Void
	{
		oTimer.delay = value;
	}
	
	
	
	/**
	 * Détruit l'objet proprement.
	 * 
	 */
	public function destroy() : Void
	{
		oTimer.removeEventListener (TimerEvent.TIMER, onDefilTxt);
		removeChild(oContainerText);
	}
}