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

import java.awt.BasicStroke;
import jp.riken.brain.ni.samuraigraph.base.SGDrawingElement;
import jp.riken.brain.ni.samuraigraph.base.SGIDrawingElementConstants;
import jp.riken.brain.ni.samuraigraph.base.SGProperties;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;


/**
 * Drawing element of the line.
 */
public abstract class SGDrawingElementLine extends SGDrawingElement
	implements SGILineConstants, SGIDrawingElementConstants
{

	/**
	 * The start point.
	 */
	private SGTuple2f mStartPoint = new SGTuple2f();


	/**
	 * The end point.
	 */
	private SGTuple2f mEndPoint = new SGTuple2f();


	/**
	 * Line type.
	 */
	private int mLineType = LINE_TYPE_SOLID;


	/**
	 * Line width.
	 */
	private float mLineWidth = 0.0f;

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


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


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


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

	

	/**
	 * Default constructor.
	 */
	public SGDrawingElementLine()
	{
		super();
	}


	/**
	 *
	 */
	public SGDrawingElementLine(
		final SGTuple2f start,
		final SGTuple2f end )
	{
		super();
		this.setTermPoints( start, end );
	}


	/**
	 *
	 */
	public SGDrawingElementLine(
		final float x1, final float y1,
		final float x2, final float y2 )
	{
		super();
		this.setTermPoints(x1,y1,x2,y2);
	}



	/**
	 * 
	 * @param el
	 */
	public SGDrawingElementLine( final SGDrawingElementLine el )
	{
		this( new SGTuple2f( el.getStart() ), new SGTuple2f( el.getEnd() ) );
		this.mLineWidth = el.getLineWidth();
		this.mLineType = el.getLineType();
	}



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



	/**
	 *
	 */
	public boolean setType( final int type )
	{
		this.mLineType = type;
		return true;
	}



	/**
	 *
	 */
	public boolean setTermPoints(
		final float x1, final float y1,
		final float x2, final float y2 )
	{
		return this.setTermPoints( new SGTuple2f(x1,y1), new SGTuple2f(x2,y2) );
	}


	/**
	 *
	 */
	public boolean setTermPoints(
		final SGTuple2f start, final SGTuple2f end )
	{
		this.mStartPoint = start;
		this.mEndPoint = end;
		return true;
	}


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


	/**
	 * 
	 * @param width
	 * @param unit
	 * @return
	 */
	public boolean setLineWidth( final float width, final String unit )
	{
		final double lw = SGUtilityText.convertToPoint( width, unit );
		if( this.setLineWidth( (float)lw ) == false )
		{
			return false;
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean setLineType( final int type )
	{
		this.mLineType = type;
		return true;
	}



	/**
	 * 
	 */
	public SGTuple2f getStart()
	{
		return this.mStartPoint;
	}


	/**
	 * 
	 */
	public SGTuple2f getEnd()
	{
		return this.mEndPoint;
	}


	/**
	 *
	 */
	public int getLineType()
	{
		return this.mLineType;
	}


	/**
	 *
	 */
	public float getLineWidth()
	{
		return this.mLineWidth;
	}


	/**
	 * 
	 * @return
	 */
	public float getMagnitude()
	{
		SGTuple2f start = this.getStart();
		SGTuple2f end = this.getEnd();
		final float xDiff = end.x - start.x;
		final float yDiff = end.y - start.y;
		final float mag = (float)Math.sqrt( xDiff*xDiff + yDiff*yDiff );
		return mag;
	}

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

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

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

	/**
	 * 
	 * @param type
	 * @return
	 */
	public static boolean isValidLineType( final int type )
	{
		return (getLineTypeName(type)!=null);
	}


	/**
	 * 
	 */
	public static Integer getLineTypeFromName( final String name )
	{

		if( name==null )
		{
			return null;
		}
		
		String str = name.toLowerCase();
		
		int type;
		if( str.equals( LINE_NAME_SOLID.toLowerCase() ) )
		{
			type = SGILineConstants.LINE_TYPE_SOLID;
		}
		else if( str.equals( LINE_NAME_BROKEN.toLowerCase() ) )
		{
			type = SGILineConstants.LINE_TYPE_BROKEN;
		}
		else if( str.equals( LINE_NAME_DOT.toLowerCase() ) )
		{
			type = SGILineConstants.LINE_TYPE_DOT;
		}
		else if( str.equals( LINE_NAME_DASHED.toLowerCase() ) )
		{
			type = SGILineConstants.LINE_TYPE_DASHED;
		}
		else if( str.equals( LINE_NAME_DOUBLE_DASHED.toLowerCase() ) )
		{
			type = SGILineConstants.LINE_TYPE_DOUBLE_DASHED;
		}
		else
		{
			return null;
		}

		return new Integer(type);
	}



	/**
	 * 
	 */
	public static String getLineTypeName( final int type )
	{
		
		String name = null;
		switch( type )
		{
			case SGILineConstants.LINE_TYPE_SOLID :
			{
				name = SGILineConstants.LINE_NAME_SOLID;
				break;
			}

			case SGILineConstants.LINE_TYPE_BROKEN :
			{
				name = SGILineConstants.LINE_NAME_BROKEN;
				break;
			}

			case SGILineConstants.LINE_TYPE_DOT :
			{
				name = SGILineConstants.LINE_NAME_DOT;
				break;
			}

			case SGILineConstants.LINE_TYPE_DASHED :
			{
				name = SGILineConstants.LINE_NAME_DASHED;
				break;
			}

			case SGILineConstants.LINE_TYPE_DOUBLE_DASHED :
			{
				name = SGILineConstants.LINE_NAME_DOUBLE_DASHED;
				break;
			}

			default :
			{
				
			}
		}
		
		return name;
	}



	/**
	 * 
	 */
	public boolean setProperties( SGProperties p )
	{

		if( ( p instanceof LineProperties ) == false ) return false;

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

		LineProperties lp = (LineProperties)p;
		Float width = lp.getLineWidth();
		if( width==null )
		{
			return false;
		}
		Integer type = lp.getLineType();
		if( type==null )
		{
			return false;
		}

		this.setLineWidth( width.floatValue() );
		this.setLineType( type.intValue() );

		return true;
	}


	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		LineProperties p = new LineProperties();
		this.getProperties(p);
		return p;
	}


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

		super.getProperties(p);

		LineProperties lp = (LineProperties)p;
		lp.setLineWidth( this.getLineWidth() );
		lp.setLineType( this.getLineType() );

		return true;
	}




	/**
	 * 
	 */
	public static class LineProperties extends DrawingElementProperties
	{
		private float mLineWidth = 0.0f;
		private int mLineType = -1;

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

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

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

			LineProperties p = (LineProperties)obj;
			if( p.mLineWidth!=this.mLineWidth ) return false;
			if( p.mLineType!=this.mLineType ) return false;

			return true;
		}


		public Float getLineWidth()
		{
			return new Float(this.mLineWidth);
		}


		public Integer getLineType()
		{
			return new Integer(this.mLineType);
		}


		public boolean setLineWidth( final float w )
		{
			if( w<0.0f )
			{
				return false;
			}
			this.mLineWidth = w;
			return true;
		}

		public boolean setLineType( final int num )
		{
			this.mLineType = num;
			return true;
		}

	}

}

