
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.SGIConstants;
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;
import org.w3c.dom.Element;


/**
 * Drawing element of axis break symbol.
 */
public abstract class SGDrawingElementAxisBreak extends SGDrawingElement
	implements SGIAxisBreakConstants, SGIDrawingElementConstants
{

	/**
	 * 
	 */
	private SGTuple2f mLocation = new SGTuple2f();

	
	/**
	 * 
	 */
	private float mLength;


	/**
	 * 
	 */
	private float mInterval;


	/**
	 * 
	 */
	private float mLineWidth;


	/**
	 * 
	 */
	private float mAngle;


	/**
	 * Value in the range [-1,1]
	 */
	private float mDistortion;


	/**
	 * 
	 */	
	private Color mLineColor;


	/**
	 * 
	 */
	private boolean mForHorizontalAxisFlag;


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


	/**
	 * 
	 */
	protected SGDrawingElementAxisBreak(
		final float length,
		final String lengthUnit,
		final float interval,
		final String intervalUnit,
		final float dist,
		final float angle,
		final boolean horizontal )
	{
		this.setLength(length,lengthUnit);
		this.setInterval(interval,intervalUnit);
		this.setDistortion(dist);
		this.setAngle(angle);
		this.setForHorizontalAxisFlag(horizontal);
	}


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


	/**
	 * 
	 * @return
	 */
	public SGTuple2f getLocation()
	{
		return this.mLocation;
	}


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


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


	/**
	 * 
	 * @return
	 */
	public final float getLength()
	{
		return this.mLength;
	}


	/**
	 * 
	 * @return
	 */
	public final float getInterval()
	{
		return this.mInterval;
	}


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


	/**
	 * 
	 * @return
	 */
	public final float getAngle()
	{
		return this.mAngle;
	}


	/**
	 * 
	 * @return
	 */
	public final float getDistortion()
	{
		return this.mDistortion;
	}


	/**
	 * 
	 * @return
	 */
	public final Color getLineColor()
	{
		return this.mLineColor;
	}


	/**
	 * 
	 * @return
	 */
	public boolean isForHorizontalAxis()
	{
		return this.mForHorizontalAxisFlag;
	}



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


	/**
	 * 
	 * @param pos
	 */
	public boolean setLocation( final SGTuple2f pos )
	{
		this.mLocation = pos;
		return true;
	}



	/**
	 * 
	 * @param value
	 */
	public boolean setLength( final float value )
	{
		if( value<0.0f )
		{
			new IllegalArgumentException("value<0.0f");
		}
		this.mLength = value;
		return true;
	}


	/**
	 * 
	 * @param value
	 */
	public boolean setInterval( final float value )
	{
		if( value<0.0f )
		{
			new IllegalArgumentException("value<0.0f");
		}
		this.mInterval = value;
		return true;
	}


	/**
	 * 
	 * @param value
	 */
	public boolean setLineWidth( final float value )
	{
		if( value<0.0f )
		{
			new IllegalArgumentException("value<0.0f");
		}
		this.mLineWidth = value;
		return true;
	}


	/**
	 * 
	 * @param angle
	 */
	public boolean setAngle( final float angle )
	{
		if( angle < AXIS_BERAK_ANGLE_MIN | AXIS_BREAK_ANGLE_MAX < angle )
		{
			return false;
		}

		this.mAngle = angle;
		return true;
	}


	/**
	 * 
	 * @param value
	 */	
	public boolean setDistortion( final float value )
	{
		this.mDistortion = value;
		return true;
	}


	/**
	 * 
	 * @param color
	 */
	public boolean setLineColor( final Color color )
	{
		if( color==null )
		{
			new IllegalArgumentException("color==null");
		}
		this.mLineColor = color;
		return true;
	}


	/**
	 * 
	 * @param flag
	 */
	public boolean setForHorizontalAxisFlag( final boolean flag )
	{
		this.mForHorizontalAxisFlag = flag;
		return true;
	}



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


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


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


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

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

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

		AxisBreakSymbolProperties ap = (AxisBreakSymbolProperties)p;

		final Float len = ap.getLength();
		if( len==null )
		{
			return false;
		}
		this.mLength = len.floatValue();
		
		
		final Float interval = ap.getInterval();
		if( interval==null )
		{
			return false;
		}
		this.mInterval = interval.floatValue();
		
		
		final Float dist = ap.getDistortion();
		if( dist==null )
		{
			return false;
		}
		this.mDistortion = dist.floatValue();


		final Float angle = ap.getAngle();
		if( angle==null )
		{
			return false;
		}
		this.mAngle = angle.floatValue();


		final Boolean horizontal = ap.isHorizontal();
		if( horizontal==null )
		{
			return false;
		}
		this.mForHorizontalAxisFlag = horizontal.booleanValue();


		final Float lw = ap.getLineWidth();
		if( lw==null )
		{
			return false;
		}
		this.mLineWidth = lw.floatValue();
		
		
		final Color lc = ap.getLineColor();
		if( lc==null )
		{
			return false;
		}
		this.mLineColor = lc;


		return true;

	}



	/**
	 * 
	 * @return
	 */
	public SGProperties getProperties()
	{
		final AxisBreakSymbolProperties p = new AxisBreakSymbolProperties();
		if( this.getProperties(p) == false )
		{
			return null;
		}
		return p;
	}


	/**
	 * 
	 * @param p
	 * @return
	 */
	public boolean getProperties( final SGProperties p )
	{
		if( ( p instanceof AxisBreakSymbolProperties ) == false )
		{
			return false;
		}

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

		final AxisBreakSymbolProperties dp = (AxisBreakSymbolProperties)p;
		dp.setLength( this.mLength );
		dp.setInterval( this.mInterval );
		dp.setDistortion( this.mDistortion );
		dp.setAngle( this.mAngle );
		dp.setHorizontal( this.mForHorizontalAxisFlag );
		dp.setLineWidth( this.mLineWidth );
		dp.setLineColor( this.mLineColor );

		return true;
	}



	/**
	 * 
	 * @param el
	 * @return
	 */
	public boolean writeProperty( final Element el )
	{
		el.setAttribute( KEY_LENGTH, Float.toString( this.mLength*SGIConstants.CM_POINT_RATIO ) + SGIConstants.cm );
		el.setAttribute( KEY_INTERVAL, Float.toString( this.mInterval*SGIConstants.CM_POINT_RATIO ) + SGIConstants.cm );
		el.setAttribute( KEY_DISTORTION, Float.toString( this.mDistortion ) );
		el.setAttribute( KEY_ANGLE, Float.toString( this.mAngle/RADIAN_DEGREE_RATIO ) + SGIConstants.degree );
		el.setAttribute( KEY_LINE_WIDTH, Float.toString( this.mLineWidth ) + SGIConstants.pt );
		el.setAttribute( KEY_HORIZONTAL, Boolean.toString( this.mForHorizontalAxisFlag ) );
		el.setAttribute( KEY_LINE_COLOR, SGUtilityText.getColorString( this.mLineColor ) );
		el.setAttribute( KEY_INNER_COLOR, SGUtilityText.getColorListString( this.getColorList() ) );
		return true;
	}


	/**
	 * 
	 */
	public boolean readProperty( final Element el )
	{
		String str = null;
		Number num = null;
		Color cl = null;
		Boolean b = null;
		List list = null;


		// width
		str = el.getAttribute( SGIAxisBreakConstants.KEY_LENGTH );
		if( str.length()!=0 )
		{
			StringBuffer uLength = new StringBuffer();
			num = SGUtilityText.getNumber( str, uLength );
			if( num==null )
			{
				return false;
			}
			final float length = num.floatValue();
			if( this.setLength( length, uLength.toString() ) == false )
			{
				return false;
			}
		}
			
			
		// interval
		str = el.getAttribute( SGIAxisBreakConstants.KEY_INTERVAL );
		if( str.length()!=0 )
		{
			StringBuffer uInterval = new StringBuffer();
			num = SGUtilityText.getNumber( str, uInterval );
			if( num==null )
			{
				return false;
			}
			final float interval = num.floatValue();
			if( this.setInterval( interval, uInterval.toString() ) == false )
			{
				return false;
			}
		}


		// distortion
		str = el.getAttribute( SGIAxisBreakConstants.KEY_DISTORTION );
		if( str.length()!=0 )
		{
			num = SGUtilityText.getFloat(str);
			if( num==null )
			{
				return false;
			}
			final float distortion = num.floatValue();
			if( this.setDistortion( distortion ) == false )
			{
				return false;
			}
		}


		// angle
		str = el.getAttribute( SGIAxisBreakConstants.KEY_ANGLE );
		if( str.length()!=0 )
		{
			num = SGUtilityText.getFloat(str,degree);
			if( num==null )
			{
				return false;
			}
			final float angle = num.floatValue()*RADIAN_DEGREE_RATIO;
			if( this.setAngle( angle ) == false )
			{
				return false;
			}
		}
			
			
		// line width
		str = el.getAttribute( SGIAxisBreakConstants.KEY_LINE_WIDTH );
		if( str.length()!=0 )
		{
			StringBuffer uLineWidth = new StringBuffer();
			num = SGUtilityText.getNumber( str, uLineWidth );
			if( num==null )
			{
				return false;
			}
			final float lineWidth = num.floatValue();
			if( this.setLineWidth( lineWidth, uLineWidth.toString() ) == false )
			{
				return false;
			}
		}


		// horizontal
		str = el.getAttribute( SGIAxisBreakConstants.KEY_HORIZONTAL );
		if( str.length()!=0 )
		{
			b = SGUtilityText.getBoolean(str);
			if( b==null )
			{
				return false;
			}
			final boolean horizontal = b.booleanValue();
			if( this.setForHorizontalAxisFlag( horizontal ) == false )
			{
				return false;
			}
		}
		

		// line color
		str = el.getAttribute( SGIAxisBreakConstants.KEY_LINE_COLOR );
		if( str.length()!=0 )
		{
			cl = SGUtilityText.getColorFromString(str);
			if( cl==null )
			{
				return false;
			}
			final Color lineColor = cl;
			if( this.setLineColor( lineColor ) == false )
			{
				return false;
			}
		}
		

		// inner color
		str = el.getAttribute( SGIAxisBreakConstants.KEY_INNER_COLOR );
		if( str.length()!=0 )
		{
			list = SGUtilityText.getColorList(str);
			if( list==null )
			{
				return false;
			}
			if( list.size()<1 )
			{
				return false;
			}
			final Color innerColor = (Color)list.get(0);
			if( this.setColor( innerColor ) == false )
			{
				return false;
			}
		}


		return true;
	}




	/**
	 * Property of Axis Break Symbol.
	 */
	public static class AxisBreakSymbolProperties extends SGDrawingElement.DrawingElementProperties
	{

		private float mX = 0.0f;
		private float mY = 0.0f;
		private float mLength = 0.0f;
		private float mInterval = 0.0f;
		private float mDistortion = 0.0f;
		private float mAngle = 0.0f;
		private float mLineWidth = 0.0f;
		private Color mLineColor = null;
		private boolean mHorizontal = true;


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


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

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

			AxisBreakSymbolProperties p = (AxisBreakSymbolProperties)obj;
			if( this.mX!=p.mX ) return false;
			if( this.mY!=p.mY ) return false;
			if( this.mLength!=p.mLength ) return false;
			if( this.mInterval!=p.mInterval ) return false;
			if( this.mDistortion!=p.mDistortion ) return false;
			if( this.mAngle!=p.mAngle ) return false;
			if( this.mLineWidth!=p.mLineWidth ) return false;
			if( this.mLineColor.equals(p.mLineColor) == false ) return false;
			if( this.mHorizontal!=p.mHorizontal ) return false;

			return true;
		}


		public Float getX()
		{
			return new Float( this.mX );
		}

		public Float getY()
		{
			return new Float( this.mY );
		}

		public Float getLength()
		{
			return new Float( this.mLength );
		}

		public Float getInterval()
		{
			return new Float( this.mInterval );
		}

		public Float getDistortion()
		{
			return new Float( this.mDistortion );
		}

		public Float getAngle()
		{
			return new Float( this.mAngle );
		}

		public Boolean isHorizontal()
		{
			return Boolean.valueOf( this.mHorizontal );
		}

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

		public Color getLineColor()
		{
			return this.mLineColor;
		}


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

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

		public boolean setLength( final float value )
		{
			if( value<0.0f )
			{
				new IllegalArgumentException("value<0.0f");
			}
			this.mLength = value;
			return true;
		}

		public boolean setInterval( final float value )
		{
			if( value<0.0f )
			{
				new IllegalArgumentException("value<0.0f");
			}
			this.mInterval = value;
			return true;
		}

		public boolean setDistortion( final float value )
		{
			if( value<0.0f )
			{
				new IllegalArgumentException("value<0.0f");
			}
			this.mDistortion = value;
			return true;
		}

		public boolean setAngle( final float value )
		{
			if( value<0.0f )
			{
				new IllegalArgumentException("value<0.0f");
			}
			this.mAngle = value;
			return true;
		}

		public boolean setHorizontal( final boolean b )
		{
			this.mHorizontal = b;
			return true;
		}

		public boolean setLineWidth( final float value )
		{
			if( value<0.0f )
			{
				new IllegalArgumentException("value<0.0f");
			}
			this.mLineWidth = value;
			return true;
		}

		public boolean setLineColor( final Color cl )
		{
			if( cl==null )
			{
				new IllegalArgumentException("cl==null");
			}
			String str = SGUtilityText.getColorString(cl);
			if( str==null )
			{
				new IllegalArgumentException("str==null");
			}
			this.mLineColor = cl;
			return true;
		}

	}



}
