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

import java.awt.Color;
import java.util.List;
import jp.riken.brain.ni.samuraigraph.base.SGDrawingElement;
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 error bar.
 */
public abstract class SGDrawingElementErrorBar extends SGDrawingElement
	implements SGIArrowConstants, SGIErrorBarConstants
{

	/**
	 * 
	 */
	private SGDrawingElementArrow mArrowElement;


	/**
	 * 
	 */
	private int mHeadType;


	/**
	 * 
	 */
	private int mErrorBarStyle = ERROR_BAR_BOTHSIDES;


	/**
	 * 
	 */
	public SGDrawingElementErrorBar()
	{
		super();
		this.mArrowElement = this.createArrowInstance();
	}

	/**
	 * 
	 */
	protected abstract SGDrawingElementArrow createArrowInstance();

	/**
	 * 
	 */
	protected final SGDrawingElementArrow getArrow()
	{
		return this.mArrowElement;
	}
	
	/**
	 * 
	 */
	public void dispose()
	{
		super.dispose();
		this.mArrowElement.dispose();
		this.mArrowElement = null;
	}


	/**
	 * 
	 */
	public static Integer getErrorBarStyleFromName( final String name )
	{
		if( name==null )
		{
			return null;
		}

		String s = name.toLowerCase();

		int style;
		if( s.equals( SHOW_FULLY.toLowerCase() ) )
		{
			style = ERROR_BAR_BOTHSIDES;
		}
		else if( s.equals( SHOW_UPPER_ONLY.toLowerCase() ) )
		{
			style = ERROR_BAR_UPSIDE;
		}
		else if( s.equals( SHOW_LOWER_ONLY.toLowerCase() ) )
		{
			style = ERROR_BAR_DOWNSIDE;
		}
		else
		{
			return null;
		}

		return new Integer(style);
	}



	/**
	 * 
	 */
	public static String getErrorBarStyleName( final int style )
	{

		String name = null;
		switch( style )
		{
			case ERROR_BAR_BOTHSIDES :
			{
				name = SHOW_FULLY;
				break;
			}

			case ERROR_BAR_UPSIDE :
			{
				name = SHOW_UPPER_ONLY;
				break;
			}

			case ERROR_BAR_DOWNSIDE :
			{
				name = SHOW_LOWER_ONLY;
				break;
			}
			
			default :
			{
				
			}
		}

		return name;
	}


	/**
	 * 
	 */
	public static Integer getHeadTypeFromName( final String name )
	{
		if( name==null )
		{
			return null;
		}
		
		String s = name.toLowerCase();
		
		int type;
		if( s.equals( SYMBOL_NAME_CIRCLE.toLowerCase() ) )
		{
			type = SGISymbolConstants.SYMBOL_TYPE_CIRCLE;
		}
		else if( s.equals( SYMBOL_NAME_TRANSVERSE_LINE.toLowerCase() ) )
		{
			type = SGISymbolConstants.SYMBOL_TYPE_TRANSVERSELINE;
		}
		else if( s.equals( NO_SYMBOL.toLowerCase() ) )
		{
			type = SGISymbolConstants.SYMBOL_TYPE_VOID;
		}
		else
		{
			return null;
		}

		return new Integer(type);
	}



	/**
	 * 
	 */
	public static String getHeadTypeName( final int type )
	{
		
		String name = null;
		switch( type )
		{
			case SGISymbolConstants.SYMBOL_TYPE_CIRCLE :
			{
				name = SYMBOL_NAME_CIRCLE;
				break;
			}

			case SGISymbolConstants.SYMBOL_TYPE_TRANSVERSELINE :
			{
				name = SYMBOL_NAME_TRANSVERSE_LINE;
				break;
			}

			case SGISymbolConstants.SYMBOL_TYPE_VOID :
			{
				name = NO_SYMBOL;
				break;
			}

			default :
			{
				
			}
		}
		
		return name;
	}



	/**
	 *
	 */
	public boolean setTermPoints( final SGTuple2f start, final SGTuple2f end )
	{
		return this.mArrowElement.setTermPoints( start, end );
	}


	/**
	 * 
	 */
	public boolean setColor( final Color cl )
	{
		super.setColor( cl );
		this.mArrowElement.setColor( cl );
		return true;
	}


	/**
	 * 
	 */
	public boolean setColorList( final List cList )
	{
		super.setColorList( cList );
		this.mArrowElement.setColorList( cList );
		return true;
	}


	/**
	 * 
	 */
	public boolean setMagnification( final float mag )
	{
		super.setMagnification( mag );
		this.mArrowElement.setMagnification( mag );
		return true;
	}


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


	/**
	 * 
	 * @param width
	 */
	public boolean setLineWidth( final float width )
	{
		return this.mArrowElement.setLineWidth( width );
	}


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


	/**
	 * 
	 * @return
	 */
	public float getHeadSize()
	{
		return this.mArrowElement.getHeadSize();
	}


	/**
	 * 
	 * @param size
	 */
	public boolean setHeadSize( final float size )
	{
		return this.mArrowElement.setHeadSize( size );
	}


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

		return true;
	}


//	/**
//	 * 
//	 * @return
//	 */
//	private int getStartHeadType()
//	{
//		return this.mArrowElement.getStartHeadType();
//	}


//	/**
//	 * 
//	 * @return
//	 */
//	private int getEndHeadType()
//	{
//		return this.mArrowElement.getEndHeadType();
//	}


	/**
	 * 
	 * @return
	 */
	public int getErrorBarStyle()
	{
		return this.mErrorBarStyle;
	}



	/**
	 * 
	 * @param style
	 * @return
	 */
	public boolean setErrorBarStyle( final int style )
	{
		this.mErrorBarStyle = style;

		final int type = this.getHeadType();
		SGDrawingElementArrow arrow = this.mArrowElement;
		switch( style )
		{
			case ERROR_BAR_BOTHSIDES :
			{
				arrow.setStartHeadType( type );
				arrow.setEndHeadType( type );
				break;
			}
			
			case ERROR_BAR_UPSIDE :
			{
				arrow.setStartHeadType( SGISymbolConstants.SYMBOL_TYPE_VOID );
				arrow.setEndHeadType( type );
				break;
			}

			case ERROR_BAR_DOWNSIDE :
			{
				arrow.setStartHeadType( type );
				arrow.setEndHeadType( SGISymbolConstants.SYMBOL_TYPE_VOID );
				break;
			}

			default :
			{
				throw new Error();
			}
		}

		return true;
	}



	/**
	 * 
	 */
	public int getHeadType()
	{
		return this.mHeadType;
	}


	/**
	 * 
	 */
	public boolean setHeadType( int type )
	{
		this.mHeadType = type;

		SGDrawingElementArrow arrow = this.mArrowElement;
		switch( this.mErrorBarStyle )
		{
			case ERROR_BAR_BOTHSIDES :
			{
				arrow.setStartHeadType(type);
				arrow.setEndHeadType(type);
				break;
			}
			
			case ERROR_BAR_UPSIDE :
			{
				arrow.setStartHeadType(SGISymbolConstants.SYMBOL_TYPE_VOID);
				arrow.setEndHeadType(type);
				break;
			}

			case ERROR_BAR_DOWNSIDE :
			{
				arrow.setStartHeadType(type);
				arrow.setEndHeadType(SGISymbolConstants.SYMBOL_TYPE_VOID);
				break;
			}

			default :
			{
				throw new Error();
			}
		}

		return true;
	}



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


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

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

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

		ErrorBarProperties ep = (ErrorBarProperties)p;

		ep.setLineWidth( this.getLineWidth() );
		ep.setHeadSize( this.getHeadSize() );
		ep.setHeadType( this.getHeadType() );
		ep.setErrorBarStyle( this.getErrorBarStyle() );

		return true;
	}



	/**
	 * @author  okumura
	 */
	public static class ErrorBarProperties extends DrawingElementProperties
	{

		private SGDrawingElementArrow.ArrowProperties mArrowProperties
			= new SGDrawingElementArrow.ArrowProperties();


		/**
		 * 
		 */
		private int mErrorBarStyle = ERROR_BAR_BOTHSIDES;


		/**
		 * 
		 */
		private int mHeadType;


		/**
		 * 
		 *
		 */
		public ErrorBarProperties()
		{
			super();
			this.mArrowProperties.setLineType( SGILineConstants.LINE_TYPE_SOLID );
		}


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

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

			ErrorBarProperties p = (ErrorBarProperties)obj;

			if( this.mArrowProperties.equals(p.mArrowProperties) == false ) return false;
			if( this.mErrorBarStyle!=p.mErrorBarStyle ) return false;
			if( this.mHeadType!=p.mHeadType ) return false;

			return true;
		}


		public Float getLineWidth()
		{
			return this.mArrowProperties.getLineWidth();
		}

		public Float getHeadSize()
		{
			return this.mArrowProperties.getHeadSize();
		}

		public Integer getHeadType()
		{
			return new Integer( this.mHeadType );
		}

		public Integer getErrorBarStyle()
		{
			return new Integer( this.mErrorBarStyle );
		}


		public void setColor( final Color cl )
		{
			super.setColor(cl);
			this.mArrowProperties.setColor(cl);
		}

		public void setColor( final List cList )
		{
			super.setColor( cList );
			this.mArrowProperties.setColor( cList );
		}


		public void setLineWidth( final float width )
		{
			this.mArrowProperties.setLineWidth( width );
		}


		public void setHeadType( final int type )
		{
			this.mHeadType = type;
			SGDrawingElementArrow.ArrowProperties p = this.mArrowProperties;

			switch( this.mErrorBarStyle )
			{
				case ERROR_BAR_BOTHSIDES :
				{
					p.setStartHeadType(type);
					p.setEndHeadType(type);
					break;
				}
			
				case ERROR_BAR_UPSIDE :
				{
					p.setStartHeadType(SGISymbolConstants.SYMBOL_TYPE_VOID);
					p.setEndHeadType(type);
					break;
				}

				case ERROR_BAR_DOWNSIDE :
				{
					p.setStartHeadType(type);
					p.setEndHeadType(SGISymbolConstants.SYMBOL_TYPE_VOID);
					break;
				}

				default :
				{
					throw new Error();
				}
			}

		}

		public void setHeadSize( final float size )
		{
			this.mArrowProperties.setHeadSize( size );
		}


		public void setErrorBarStyle( final int style )
		{
			this.mErrorBarStyle = style;

			final int type = this.getHeadType().intValue();
			SGDrawingElementArrow.ArrowProperties p = this.mArrowProperties;
			switch( style )
			{
				case ERROR_BAR_BOTHSIDES :
				{
					p.setStartHeadType( type );
					p.setEndHeadType( type );
					break;
				}
			
				case ERROR_BAR_UPSIDE :
				{
					p.setStartHeadType( SGISymbolConstants.SYMBOL_TYPE_VOID );
					p.setEndHeadType( type );
					break;
				}

				case ERROR_BAR_DOWNSIDE :
				{
					p.setStartHeadType( type );
					p.setEndHeadType( SGISymbolConstants.SYMBOL_TYPE_VOID );
					break;
				}

				default :
				{
					throw new Error();
				}
			}

		}

	}


}


