package org.papervision3d.typography {
	import org.papervision3d.core.proto.MaterialObject3D;
	import org.papervision3d.materials.special.Letter3DMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.special.VectorShape3D;	

	/**
	 * @author Mark Barcinski
	 */
	public class Text3D extends VectorShape3D {
		public var letters : Array;
		
		protected var _text : String;
		public var font : Font3D;
		
		public var lines : Array;
		
		
		private var _letterSpacing : Number = 0;
		private var _lineSpacing : Number = 0;
		private var _align : String = "center";
		
		private var _lineHeight : Number = 0;
		
			
		public function Text3D(text:String , font : Font3D , material : MaterialObject3D, 
								name : String = null ) {
			//super(name, geometry);
			//TODO temp stuff , revert textfield back to displayobject after debug
			super(material, null , name);
			
			this.material = material;
			this.font = font;
			_text = text.replace(/\r/gi, "\n");
			
			//letters = [];
			
			_lineHeight = font.height + _lineSpacing;
			
			
			createLetters(material);
			alignLetters();
			
		}
		
		protected function createLetters( material : MaterialObject3D ) : void 
		{
			lines = [];
			letters = [];
			var textLine:String;
			var textLines:Array = _text.split("\n");
			var letter : VectorLetter3D;
			var lineLetters : Array;
			
			for (var i:int = 0 ; i < textLines.length ; i++)
			{
				lineLetters = new Array();
				lines[i] = lineLetters;
				textLine = textLines[i];
				
				for(var j:int = 0 ; j < textLine.length ; j++)
				{
					var char:String = textLine.charAt(j);
					letter = new VectorLetter3D(char, material as Letter3DMaterial, font );
					
					lineLetters.push(letter);
					if(char != " ") addChild(letter);	
					letters.push(letter);
				}
			}
		}
		
		private function alignLetters() : void 
		{
			var letter : Letter3D;
			var prevLetter : Letter3D;
			var lineLetters : Array;
			var currY:Number = 0;
			
			
			// used for align
			var first : Letter3D;
			var last  : Letter3D;
			var tx : Number;
			
			for (var i:int = 0 ; i < lines.length ; i++)
			{
				lineLetters = lines[i];
				currY = i * - _lineHeight;
				
				first = lineLetters[0];
				last = lineLetters[lineLetters.length-1];
				
				for(var j:int = 0 ; j < lineLetters.length ; j++)
				{
					letter = lineLetters[j];
					
					letter.x = j > 0 ? prevLetter.x + (prevLetter.width/2 + letter.width/2)  + _letterSpacing : letter.width / 2;
					letter.y = currY;
					
					prevLetter = letter;
				}
				
				if(align == "center" && last){
					tx = ( last.x + last.width/2) / 2;
					for(j = 0 ; j < lineLetters.length ; j++)
					{
						DisplayObject3D(lineLetters[j]).x -= tx;		
					}
				}
				
				if(align == "right" && last){
					tx = last.x + last.width/2;
					for(j = 0 ; j < lineLetters.length ; j++)
					{
						DisplayObject3D(lineLetters[j]).x -= tx;		
					}
				}				
			}
		}
		
		private function removeLetters():void {
			for each( var l:DisplayObject3D in letters){
				removeChild(l);	
			}
			
			letters.length = 0;
			lines.length = 0;
		}
		
		
		///////////////////////////////////////////////
		// getters and setters
		///////////////////////////////////////////////
				
		public function get letterSpacing() : Number {
			return _letterSpacing;
		}
		
		public function set letterSpacing(spacing : Number) : void {
			_letterSpacing = spacing;
			
			alignLetters();
		}
		
		public function get lineSpacing() : Number {
			return _lineSpacing;
		}
		
		public function set lineSpacing(lineSpacing : Number) : void {
			_lineSpacing = lineSpacing;
			_lineHeight = font.height + lineSpacing; 
			
			alignLetters();
		}
		
		public function get align() : String {
			return _align;
		}
		
		public function set align(align : String) : void {
			_align = align;
			
			alignLetters();
		}
		
		public function get text() : String {
			return _text;
		}
		
		public function set text(text : String) : void {
			_text = text.replace(/\r/gi, "\n");
			
			removeLetters();
			
			createLetters(Letter3DMaterial(material));
			alignLetters();
		}
	}
}
