

package jp.riken.brain.ni.samuraigraph.figure;

import java.awt.BasicStroke;
import java.awt.Color;
import java.util.List;

import jp.riken.brain.ni.samuraigraph.base.SGDrawingElement;
import jp.riken.brain.ni.samuraigraph.base.SGIConstants;
import jp.riken.brain.ni.samuraigraph.base.SGProperties;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;

import org.w3c.dom.Element;


/**
 * Drawing element of the rectangle.
 * 
 */
public abstract class SGDrawingElementRectangle extends SGDrawingElement
	implements SGIRectangleConstants
{

	/**
	 * 
	 */
	private float mX;


	/**
	 * 
	 */
	private float mY;


	/**
	 * Width of the rectangle.
	 * The negative value is permitted.
	 */
	private float mWidth;

	/**
	 * Height of the rectangle.
	 * The negative value is permitted.
	 */
	private float mHeight;


	/**
	 * 
	 */
	private float mEdgeLineWidth;


	/**
	 * 
	 */
	private int mEdgeLineType;


	/**
	 * 
	 */
	private Color mEdgeLineColor;


	/**
	 * 
	 */
	private boolean mTransparentFlag;



	/**
	 * 
	 */
	private int mCap = BasicStroke.CAP_BUTT;


	/**
	 * 
	 */
	private int mJoin = BasicStroke.JOIN_ROUND;


	/**
	 * 
	 */
	private float mMiterLimit = 1.0f;


	/**
	 * 
	 */
	private float mDashPhase = 0.0f;



	/**
	 * 
	 */
	public SGDrawingElementRectangle()
	{
		super();
	}



	/**
	 * 
	 */
	public void dispose()
	{
		super.dispose();
		this.mEdgeLineColor = null;
	}


	/**
	 * 
	 */
	public float getX()
	{
		return this.mX;
	}


	/**
	 * 
	 */
	public float getY()
	{
		return this.mY;
	}


	/**
	 * 
	 * @return
	 */
	public SGTuple2f getLocation()
	{
		return new SGTuple2f( this.getX(), this.getY() );
	}


	/**
	 * 
	 */
	public float getWidth()
	{
		return this.mWidth;
	}


	/**
	 * 
	 */
	public float getHeight()
	{
		return this.mHeight;
	}


	/**
	 * 
	 */
	public float getEdgeLineWidth()
	{
		return this.mEdgeLineWidth;
	}


	/**
	 * 
	 */
	public Color getEdgeLineColor()
	{
		return this.mEdgeLineColor;
	}


	/**
	 * 
	 * @return
	 */
	public int getEdgeLineType()
	{
		return this.mEdgeLineType;
	}


	/**
	 * 
	 * @return
	 */
	public boolean isTransparent()
	{
		return this.mTransparentFlag;
	}

	
	/**
	 * 
	 */
	protected int getStrokeCap()
	{
		return this.mCap;
	}

	protected int getStrokeJoin()
	{
		return this.mJoin;
	}

	protected float getStrokeMiterLimit()
	{
		return this.mMiterLimit;
	}
	
	protected float getStrokeDashPhase()
	{
		return this.mDashPhase;
	}

	/**
	 * 
	 */
	public boolean setEdgeLineWidth( final float width )
	{
		this.mEdgeLineWidth = width;
		return true;
	}


	/**
	 * 
	 * @param width
	 * @param unit
	 * @return
	 */
	public boolean setEdgeLineWidth( final float width, final String unit )
	{
		return this.setEdgeLineWidth( (float)SGUtilityText.convertToPoint( width, unit ) );
	}


	/**
	 * 
	 * @param type
	 * @return
	 */
	public boolean setEdgeLineType( final int type )
	{
		this.mEdgeLineType = type;
		return true;
	}


	/**
	 * 
	 */
	public boolean setEdgeLineColor( final Color color )
	{
		this.mEdgeLineColor = color;
		return true;
	}


	/**
	 * 
	 */
	public boolean setTransparent( final boolean b )
	{
		this.mTransparentFlag = b;
		return true;
	}


	/**
	 * 
	 */
	public boolean setX( final float x )
	{
		this.mX = x;
		return true;
	}


	/**
	 * 
	 */
	public boolean setY( final float y )
	{
		this.mY = y;
		return true;
	}


	/**
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean setLocation( final float x, final float y )
	{
		this.setX(x);
		this.setY(y);
		return true;
	}


	/**
	 * 
	 * @param point
	 * @return
	 */
	public boolean setLocation( final SGTuple2f point )
	{
		this.setLocation( point.x, point.y );
		return true;
	}


	/**
	 * 
	 */
	public boolean setWidth( final float w )
	{
		this.mWidth = w;
		return true;
	}


	/**
	 * 
	 */
	public boolean setWidth( final float w, final String unit )
	{
		return this.setWidth( (float)SGUtilityText.convertToPoint( w, unit ) );
	}


	/**
	 * 
	 */
	public boolean setHeight( final float h )
	{
		this.mHeight = h;
		return true;
	}


	/**
	 * 
	 */
	public boolean setHeight( final float h, final String unit )
	{
		return this.setHeight( (float)SGUtilityText.convertToPoint( h, unit ) );
	}


	/**
	 * 
	 * @param w
	 * @param h
	 * @return
	 */
	public boolean setSize( final float w, final float h )
	{
		this.setWidth(w);
		this.setHeight(h);
		return true;
	}


	/**
	 * 
	 */
	public boolean setBounds(
		final float x,
		final float y,
		final float w,
		final float h )
	{
		this.setLocation(x,y);
		this.setSize(w,h);		
		return true;		
	}



	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		RectangleProperties p = new RectangleProperties();

		if( this.getProperties(p) == false ) return null;

		return p;
	}




	/**
	 * 
	 */
	public boolean getProperties( SGProperties p )
	{
		if( ( p instanceof RectangleProperties ) == false ) return false;

		if( super.getProperties(p) == false ) return false;

		RectangleProperties bp = (RectangleProperties)p;
		bp.setHeight( this.getHeight() );
		bp.setWidth( this.getWidth() );
		bp.setEdgeLineWidth( this.getEdgeLineWidth() );
		bp.setEdgeLineType( this.getEdgeLineType() );
		bp.setEdgeLineColor( this.getEdgeLineColor() );
		bp.setTransparent( this.isTransparent() );

		return true;
	}



	/**
	 * 
	 */
	public boolean setProperties( SGProperties p )
	{
		if( ( p instanceof RectangleProperties ) == false ) return false;

		if( super.setProperties(p) == false ) return false;

		RectangleProperties bp = (RectangleProperties)p;

		final Float width = bp.getWidth();
		if( width==null )
		{
			return false;
		}
		this.setWidth( width.floatValue() );

		final Float height = bp.getHeight();
		if( height==null )
		{
			return false;
		}
		this.setHeight( height.floatValue() );
		
		final Float edgeLineWidth = bp.getEdgeLineWidth();
		if( edgeLineWidth==null )
		{
			return false;
		}
		this.setEdgeLineWidth( edgeLineWidth.floatValue() );

		final int edgeLineType = bp.getEdgeLineType();
		if( edgeLineType==-1 )
		{
			return false;
		}
		this.setEdgeLineType( edgeLineType );

		final Color edgeLineColor = bp.getEdgeLineColor();
		if( edgeLineColor==null )
		{
			return false;
		}
		this.setEdgeLineColor( edgeLineColor );

		this.setTransparent( bp.isTransparent() );

		return true;
	}



	/**
	 * 
	 */
	public boolean writeProperty( final Element el )
	{
//		final float ratio = SGIConstants.CM_POINT_RATIO;

		el.setAttribute( KEY_EDGE_LINE_WIDTH, Float.toString( this.mEdgeLineWidth ) + SGIConstants.pt );
		el.setAttribute( KEY_EDGE_LINE_TYPE, SGDrawingElementLine.getLineTypeName( this.getEdgeLineType() ) );
		el.setAttribute( KEY_BACKGROUND_TRANSPARENT, Boolean.toString( this.isTransparent() ) );
		el.setAttribute( KEY_INNER_COLOR, SGUtilityText.getColorListString( this.getColorList() ) );
		el.setAttribute( KEY_EDGE_LINE_COLOR, SGUtilityText.getColorString( this.mEdgeLineColor ) );

		return true;
	}


	/**
	 * 
	 */
	public boolean readProperty( final Element el )
	{
//		final float ratio = SGIConstants.CM_POINT_RATIO;

		String str = null;
		Number num = null;
		Color cl = null;
		Boolean b = null;
		List list = null;


		// edge line width
		str = el.getAttribute( KEY_EDGE_LINE_WIDTH );
		if( str.length()!=0 )
		{
			StringBuffer uEdgeLineWidth = new StringBuffer();
			num = SGUtilityText.getNumber( str, uEdgeLineWidth );
			if( num==null )
			{
				return false;
			}
			final float edgeLineWidth = num.floatValue();
			if( this.setEdgeLineWidth( edgeLineWidth, uEdgeLineWidth.toString() ) == false )
			{
				return false;
			}
		}


		// edge line type
		str = el.getAttribute( KEY_EDGE_LINE_TYPE );
		if( str.length()!=0 )
		{
			num = SGDrawingElementLine.getLineTypeFromName(str);
			if( num==null )
			{
				return false;
			}
			final int edgeLineType = num.intValue();
			if( this.setEdgeLineType( edgeLineType ) == false )
			{
				return false;
			}
		}


		// transparent
		str = el.getAttribute( KEY_BACKGROUND_TRANSPARENT );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b==null )
			{
				return false;
			}
			final boolean transparent = b.booleanValue();
			if( this.setTransparent( transparent ) == false )
			{
				return false;
			}
		}


		// inner color
		str = el.getAttribute( KEY_INNER_COLOR );
		if( str.length()!=0 )
		{
			list = SGUtilityText.getColorList(str);
			if( list==null )
			{
				return false;
			}
			if( this.setColorList( list ) == false )
			{
				return false;
			}
		}
		

		// edge line color
		str = el.getAttribute( KEY_EDGE_LINE_COLOR );
		if( str.length()!=0 )
		{
			cl = SGUtilityText.getColorFromString(str);
			if( cl==null )
			{
				return false;
			}
			final Color edgeLineColor = cl;
			if( this.setEdgeLineColor( edgeLineColor ) == false )
			{
				return false;
			}
		}
	
		return true;
	}



	/**
	 * 
	 */
	public static class RectangleProperties extends DrawingElementProperties
	{
		private float mWidth = 0.0f;
		private float mHeight = 0.0f;
		private float mEdgeLineWidth = 0.0f;
		private int mEdgeLineType = -1;
		private Color mEdgeLineColor = null;
		private boolean mTransparent = false;

		/**
		 * 
		 */
		public RectangleProperties()
		{
			super();
		}


		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{
			if( ( obj instanceof RectangleProperties ) == false )
			{
				return false;
			}

			if( super.equals(obj) == false ) return false;

			RectangleProperties p = (RectangleProperties)obj;
			if( this.mWidth!=p.mWidth ) return false;
			if( this.mHeight!=p.mHeight ) return false;
			if( this.mEdgeLineWidth!=p.mEdgeLineWidth ) return false;
			if( this.mEdgeLineType!=p.mEdgeLineType ) return false;
			if( this.mEdgeLineColor.equals(p.mEdgeLineColor) == false ) return false;
			if( this.mTransparent!=p.mTransparent ) return false;

			return true;
		}


		public Float getWidth()
		{
			return new Float( this.mWidth );
		}

		public Float getHeight()
		{
			return new Float( this.mHeight );
		}

		public Float getEdgeLineWidth()
		{
			return new Float( this.mEdgeLineWidth );
		}

		public int getEdgeLineType()
		{
			return this.mEdgeLineType;
		}

		public Color getEdgeLineColor()
		{
			return this.mEdgeLineColor;
		}

		public boolean isTransparent()
		{
			return this.mTransparent;
		}

		public boolean setWidth( final float value )
		{
			this.mWidth = value;
			return true;
		}

		public boolean setHeight( final float value )
		{
			this.mHeight = value;
			return true;
		}

		public boolean setEdgeLineWidth( final float width )
		{
			if( width<0.0f )
			{
				throw new IllegalArgumentException("width<0.0f");
			}
			this.mEdgeLineWidth = width;
			return true;
		}

		public boolean setEdgeLineType( final int type )
		{
			this.mEdgeLineType = type;
			return true;
		}

		public boolean setEdgeLineColor( final Color cl )
		{
			if( cl==null )
			{
				throw new IllegalArgumentException("cl==null");
			}
			this.mEdgeLineColor = cl;
			return true;
		}

		public boolean setTransparent( final boolean b )
		{
			this.mTransparent = b;
			return true;
		}

	}


}
