
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;


/**
 *
 */

public abstract class SGDrawingElementLine extends SGDrawingElement
	implements SGILineConstants, SGIDrawingElementConstants
{

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


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


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


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

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


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


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


	/**
	 * 
	 */
	protected 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 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;
	}


	/**
	 * 
	 */
	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;
	}



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

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

		return new Integer(type);
	}



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

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

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

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

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

			default :
			{
				
			}
		}
		
		return name;
	}



	/**
	 * 
	 */
	public boolean setProperty( final SGDrawingElement element )
	{
		if( !(element instanceof SGDrawingElementLine) )
		{
			return false;
		}

		if( super.setProperty( element ) == false )
		{
			return false;
		}

		SGDrawingElementLine line = (SGDrawingElementLine)element;

		this.setLineType( line.getLineType() );
		this.setLineWidth( line.getLineWidth() );
	
		return true;
	}


	/**
	 * 
	 */
	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
	{

		public static final String[] keys = {
			KEY_LINE_WIDTH, KEY_LINE_TYPE
		};


		/**
		 *
		 */
		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;
			for( int ii=0; ii<keys.length; ii++ )
			{
				if( this.getProperty(keys[ii]).equals(p.getProperty(keys[ii])) == false )
				{
					return false;
				}
			}

			return true;
		}


		public Float getLineWidth()
		{
			final String value = this.getProperty(KEY_LINE_WIDTH);
			return SGUtilityText.getFloat(value);
		}


		public Integer getLineType()
		{
			final String value = this.getProperty(KEY_LINE_TYPE);
			return SGUtilityText.getInteger(value);
		}


		public boolean setLineWidth( final float w )
		{
			if( w<0.0f )
			{
				return false;
			}
			this.setProperty( KEY_LINE_WIDTH, new Float(w).toString() );
			return true;
		}

		public boolean setLineType( final int num )
		{
			this.setProperty( KEY_LINE_TYPE, new Integer(num).toString() );
			return true;
		}


	}



}
