import flash.text.TextField;
import flash.text.TextFormat;
import flash.display3D.Context3D;

import flash.xml.XML;
import flash.xml.XMLList;
import flash.xml.XMLParser;

class WMLabel extends WMObjBase {
  public var font( __getFontName, __setFontName ):String;
    public function __getFontName():String { return( font ); }
    public function __setFontName( fn:String ):String {
      font = fn;
      return( font );
    }
  public var fontsize( __getFontSize, __setFontSize ):Float;
    public function __getFontSize():Float { return( fontsize ); }
    public function __setFontSize( fs:Float ):Float {
      fontsize = fs;
      return( fontsize );
    }
  public var text( __getText, __setText ):String;
    public function __getText():String { return( text ); }
    public function __setText( t:String ):String {
      text = t;
      return( t );
    }
  public var pos( __getPos, __setPos ):Point3D;
    public function __getPos():Point3D { return( pos ); }
    public function __setPos( p:Point3D ):Point3D {
      if ( p != null ) pos = p.clone();
      return( pos );
    }
  public var opos( __getOrgPos, __setOrgPos ):Point3D;
    public function __getOrgPos():Point3D { return( opos ); }
    public function __setOrgPos( p:Point3D ):Point3D {
      if ( p != null ) opos = p.clone();
      return( opos );
    }

  // ####################################################################

  public function new( ?r:Float = 130.0,
                       ?c0:Int = 0x000000,
                       ?c1:Int = 0x000000,
                       ?a:Float = 1.0,
                       ?o:Float = 0.0,
                       ?q:Int = 0,
                       ?ag:Float = 0.0,
                       ?d:Float = 0.0,
                       ?sp:Float = 0.0,
                       ?gl:Float = 20.0,
                       ?sh:String = "2DUV" ) {
    super( r, c0, c1, a, o, q, ag, d, sp, gl, sh );
    pos = null;
    opos = null;
    font = "Arial";
    fontsize = 32.0;
    text = "";
  }

  public function clone():WMLabel {
    var ret:WMLabel = new WMLabel( radius, color0, color1, alpha, offset, quality, ambient, diffuse, specular, gloss, shader );
    ret.font = font;
    ret.fontsize = fontsize;
    return( ret );
  }

  public override function clear( ?def:WMDefaults = null ):Void {
    if ( def != null ) {
      copyFrom( def.Label );
      font = def.LabelFont;
      fontsize = def.LabelSize;
    } else {
      radius = 130.0;
      alpha = 1.0;
      font = "Arial";
      fontsize = 32.0;
    }
    pos = null;
    opos = null;
    text = "";
    _polygon = null;
  }

  public override function loadFromXml( x:Xml,
                                        ?def:WMDefaults = null ):Void {
    clear( def );
    loadFromXmlWOClear( x );
  }

  public function loadFromXmlOverwrite( x:Xml ):Void {
    super.loadFromXml( x );
    if ( x.exists( "font" ) ) font = x.get( "font" );
    if ( x.exists( "fontsize" ) ) fontsize = Std.parseFloat( x.get( "fontsize" ) );
    shader = "2DUV"; // only applicable shader
  }

  public function loadFromXmlWOClear( x:Xml ):Void {
    loadFromXmlOverwrite( x );
    if ( !x.exists( "pos" ) || !x.exists( "text" ) ) {
      trace( "pos and text attributes are required for a LABEL element." );
      return;
    }
    pos = Point3D.fromString( x.get( "pos" ) );
    opos = pos;
    text = x.get( "text" );
  }

  public function gen( c:Context3D ):Void {
    var tf:TextField = new TextField();
    tf.text = text;
    tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
    tf.selectable = false;
    // larger font size might be better to draw smooth character
    tf.setTextFormat( new TextFormat( font, fontsize, color0, true, null, null, null, flash.text.TextFormatAlign.LEFT ) );
    var aspect:Float = tf.width / tf.height;
    //_polygon = new Text3D( tf.width * scale, tf.height * scale );
    _polygon = new Text3D( aspect * radius, radius );
    _polygon.translate( pos.x, pos.y, pos.z );
    _polygon.createTextTexture( c, tf );
    _polygon.allocate( c, shader, color0, alpha );
  }

  public function num():Int { return(1); }
  public function sumPos():Point3D { return( pos ); }
  public function translate( p:Point3D ):Void { pos.add( p ); }
  public function absmax():Point3D {
    return( new Point3D( Math.abs( pos.x ), Math.abs( pos.y ), Math.abs( pos.z ) ) );
  }
  public function scaleCoord( scale:Float ):Void {
    pos.multiply( scale );
  }
  public override function getDataSize():Int { return(3); }
}
