import flash.display3D.Context3D;

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

class WMRibbon extends WMObjBase {
  public var isRibbon( __getIsRibbon, __setIsRibbon ):Bool;

  public var initXML( __getInitXML, __setInitXML ):Int;
  public var lastXML( __getLastXML, __setLastXML ):Int;
  public var init( __getInit, __setInit ):Int;
  public var last( __getLast, __setLast ):Int;
  public var thickness( __getThickness, __setThickness ):Float;

  public function new( ?i:Bool = false,
                       ?r:Float = 3.0,
                       ?c0:Int = 0x00FF00,
                       ?c1:Int = 0x00FF00,
                       ?a:Float = 1.0,
                       ?o:Float = 0.0,
                       ?q:Int = 0,
                       ?ag:Float = 0.3,
                       ?d:Float = 0.7,
                       ?sp:Float = 0.8,
                       ?gl:Float = 10.0,
                       ?sh:String = "Gouraud" ) {
    super( r, c0, c1, a, o, q, ag, d, sp, gl, sh );
    isRibbon = i;
    initXML = lastXML = -1;
    init = last = -1;
    thickness = 0.0;
  }

  public function clone():WMRibbon {
    var ret:WMRibbon = new WMRibbon( isRibbon, radius, color0, color1, alpha, offset, quality, ambient, diffuse, specular, gloss, shader );
    ret.init = init;
    ret.initXML = initXML;
    ret.last = last;
    ret.lastXML = lastXML;
    ret.thickness = thickness;
    return( ret );
  }

  public override function clear( ?def:WMDefaults = null ):Void {
    if ( def != null ) {
      if ( isRibbon ) {
        copyFrom( def.Ribbon );
        thickness = def.RibbonThickness;
      } else {
        copyFrom( def.Coil );
      }
    } else {
      isRibbon = false;
      radius = 3.0;
      color0 = 0x00FF00;
      color1 = 0x00FF00;
      alpha = 1.0;
      offset = 0.0;
      quality = 0;
      ambient = 0.3;
      diffuse = 0.7;
      specular = 0.8;
      gloss = 10.0;
      shader = "Gouraud";
      thickness = 0.0;
    }
    _polygon = null;
    initXML = lastXML = -1;
  }

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

  public function loadFromXmlOverwrite( x:Xml ):Void {
    super.loadFromXml( x );
    var strs = [ "thick", "thickness" ];
    for ( str in strs ) {
      if ( x.exists( str ) ) {
        thickness = Std.parseFloat( x.get( str ) );
      }
    }
  }

  // what a ad hoc function...
  public function loadFromXmlWOClear( x:Xml ):Void {
    loadFromXmlOverwrite( x );
    if ( !x.exists( "init" ) || !x.exists( "last" ) ) {
      trace( "init and last attributes are required for a RIBBON or COIL element" );
      return;
    }
    initXML = Std.parseInt( x.get( "init" ) );
    lastXML = Std.parseInt( x.get( "last" ) );
  }

  public function gen( c:Context3D,
                       chain:SmoothChain ):Void {
    if ( color0 != color1 ) {
      if ( shader == "Gouraud" ) shader = "GouraudUV";
      if ( shader == "Phong" ) shader = "PhongUV";
    }
    if ( isRibbon ) {
      _polygon = chain.genRibbon( WMBase.getRelative( radius ),
                                  WMBase.getRelative( thickness ),
                                  init, last + 1 );
    } else {
      _polygon = chain.genCoil( WMBase.getRelative( radius ), quality,
                                init, last + 1 );
    }
    _polygon.allocate( c, shader, color0, alpha );
    // replace texture if neccessary
    if ( color0 != color1 ) {
      _polygon.createGradientTexture( c, color0, color1 );
    }
  }

  public function __getIsRibbon():Bool { return( isRibbon ); }
  public function __getInitXML():Int { return( initXML ); }
  public function __getLastXML():Int { return( lastXML ); }
  public function __getInit():Int { return( init ); }
  public function __getLast():Int { return( last ); }
  public function __getThickness():Float { return( thickness ); }
  public function __setIsRibbon( i:Bool ):Bool {
    isRibbon = i;
    return( isRibbon );
  }
  public function __setInitXML( n:Int ):Int {
    initXML = n;
    return( initXML );
  }
  public function __setLastXML( n:Int ):Int {
    lastXML = n;
    return( lastXML );
  }
  public function __setInit( n:Int ):Int {
    init = n;
    return( init );
  }
  public function __setLast( n:Int ):Int {
    last = n;
    return( last );
  }
  public function __setThickness( t:Float ):Float {
    thickness = t;
    return( t );
  }
}
