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

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

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.SGUtilityNumber;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementBar;
import jp.riken.brain.ni.samuraigraph.figure.SGIBarConstants;

import org.w3c.dom.Element;


/**
 *
 */
public abstract class SGElementGroupBar extends SGElementGroupRectangle
	implements SGIBarConstants, SGIElementGroupConstants
{


	/**
	 * 
	 */
	protected double mBaselineValue;


	/**
	 * 
	 */
	protected double mWidthValue;


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



	/**
	 * 
	 */
	public double getBaselineValue()
	{
		return this.mBaselineValue;
	}


	/**
	 * 
	 */
	public boolean setBaselineValue( final double value )
	{
		this.mBaselineValue = value;
		return true;
	}


	/**
	 * 
	 */
	public double getWidthValue()
	{
		return this.mWidthValue;
	}


	/**
	 * 
	 */
	public boolean setWidthValue( final double value )
	{
		this.mWidthValue = value;
		return true;
	}


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

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

		SGDrawingElementBar bar = (SGDrawingElementBar)element;
		this.setBaselineValue( bar.getBaselineValue() );
		this.setWidthValue( bar.getWidthValue() );

		return true;
	}



	/**
	 * 
	 */
	public boolean paintElement(
		final Graphics2D g2d, final Rectangle2D clipRect )
	{
		SGDrawingElement[] array = this.mDrawingElementArray;
		if( array!=null )
		{
			for( int ii=0; ii<array.length; ii++ )
			{
				SGDrawingElementBar2D el
					= (SGDrawingElementBar2D)array[ii];
				el.paint( g2d, clipRect );
			}
		}

		return true;
	}



	/**
	 * 
	 */
	public SGDrawingElement getDrawingElement()
	{
		SGDrawingElementBar rect = new SGDrawingElementBar2D();
		rect.setVisible( this.mVisibleFlag );
//		rect.setWidth( this.mRectangleWidth );
//		rect.setHeight( this.mRectangleHeight );
		rect.setEdgeLineWidth( this.mEdgeLineWidth );
		rect.setEdgeLineColor( this.mEdgeLineColor );
		rect.setColor( this.mColorList );
		rect.setBaselineValue( this.mBaselineValue );
		rect.setWidthValue( this.mWidthValue );

		return rect;
	}



	
	/**
	 * 
	 * @return
	 */
	public String getTagName()
	{
		return TAG_NAME_BAR;
	}

	
	/**
	 * 
	 */
	public boolean writeProperty( final Element el )
	{
		final String cm = SGUtilityNumber.cm;
		final String pt = SGUtilityNumber.pt;
		el.setAttribute( KEY_VISIBLE, Boolean.toString( this.mVisibleFlag ) );
//		el.setAttribute( KEY_RECTANGLE_WIDTH, Float.toString( this.mRectangleWidth*SGIConstants.CM_POINT_RATIO ) + cm );
		el.setAttribute( KEY_RECTANGLE_WIDTH_VALUE, Double.toString( this.mWidthValue ) );
		el.setAttribute( KEY_EDGE_LINE_WIDTH, Float.toString( this.mEdgeLineWidth ) + pt );
		el.setAttribute( KEY_BASELINE_VALUE, Double.toString( this.mBaselineValue ) );
		el.setAttribute( KEY_COLOR_LIST, SGUtilityText.getColorListString( this.mColorList ) );
		el.setAttribute( KEY_EDGE_LINE_COLOR, SGUtilityText.getColorString( this.mEdgeLineColor ) );
		return true;
	}

	

	
	/**
	 * 
	 * @param el
	 * @return
	 */
	public SGProperties readProperties( final Element el )
	{
		final String cm = SGUtilityNumber.cm;
		final String pt = SGUtilityNumber.pt;
		final float ratio = SGIConstants.CM_POINT_RATIO;

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

		BarProperties p = new BarProperties();

		
		// visible
		str = el.getAttribute( KEY_VISIBLE );
		if( str.length()==0 )
		{
			return null;
		}
		b = SGUtilityText.getBoolean(str);
		if( b==null )
		{
			return null;
		}
		p.setVisible( b.booleanValue() );


		// width of the bar
		str = el.getAttribute( KEY_RECTANGLE_WIDTH_VALUE );
		if( str.length()==0 )
		{
// The attribute of width-value is added from version 0.9.1
// This code is for the old versions.

			str = el.getAttribute( KEY_RECTANGLE_WIDTH );
			if( str.length()==0 )
			{
				return null;
			}
			num = SGUtilityText.getFloat(str,cm);
			if( num==null )
			{
				return null;
			}
			p.setBarWidth( num.floatValue()/ratio );
		}
		else
		{
			num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return null;
			}
			p.setWidthValue( num.doubleValue() );
		}



		// inner color list
		str = el.getAttribute( KEY_COLOR_LIST );
		if( str.length()==0 )
		{
			return null;
		}
		list = SGUtilityText.getColorList(str);
		if( list==null )
		{
			return null;
		}
		p.setColorList( list );


		// edge line width
		str = el.getAttribute( KEY_EDGE_LINE_WIDTH );
		if( str.length()==0 )
		{
			return null;
		}
		num = SGUtilityText.getLengthInPoint( str );
		if( num==null )
		{
			return null;
		}
		p.setEdgeLineWidth( num.floatValue() );


		// baseline value
		str = el.getAttribute( KEY_BASELINE_VALUE );
		if( str.length()==0 )
		{
			return null;
		}
		num = SGUtilityText.getDouble(str);
		if( num==null )
		{
			return null;
		}
		p.setBaselineValue( num.doubleValue() );


		// edge line color
		str = el.getAttribute( KEY_EDGE_LINE_COLOR );
		if( str.length()==0 )
		{
			return null;
		}
		cl = SGUtilityText.getColorFromString(str);
		if( cl==null )
		{
			return null;
		}
		p.setEdgeLineColor( cl );
		
		
		return p;
	}

	

	/**
	 * 
	 * @return
	 */
	protected boolean initDrawingElement( final int num )
	{
		SGDrawingElementBar2D[] array = new SGDrawingElementBar2D[num];
		for( int ii=0; ii<num; ii++ )
		{
			array[ii] = new SGDrawingElementBar2D();
		}
		this.mDrawingElementArray = array;
		return true;
	}


	/**
	 * 
	 * @return
	 */
	protected boolean initDrawingElement( final SGTuple2f[] array )
	{
		final int num = array.length;
		SGDrawingElementBar2D[] bArray = new SGDrawingElementBar2D[num];
		for( int ii=0; ii<num; ii++ )
		{
			bArray[ii] = new SGDrawingElementBar2D();
			bArray[ii].setLocation( array[ii].x, array[ii].y );
		}
		this.mDrawingElementArray = bArray;
		return true;
	}


	/**
	 * 
	 */
	public boolean setLocation(
		final SGTuple2f[] pointArray )
	{

		if( this.mDrawingElementArray==null )
		{
			return true;
		}

		if( pointArray.length != this.mDrawingElementArray.length )
		{
			throw new IllegalArgumentException();
		}

		// 棒グラフの描画要素を作成
		SGDrawingElement[] array = this.mDrawingElementArray;
		for( int ii=0; ii<array.length; ii++ )
		{
			SGDrawingElementBar2D bar = (SGDrawingElementBar2D)array[ii];
			final boolean eff = !( pointArray[ii].isInfinite() | pointArray[ii].isNaN() );
			bar.setVisible( eff );
			if( eff )
			{
				bar.setLocation( pointArray[ii] );
			}
		}

		return true;
	}



	/**
	 * 
	 * @param value
	 * @return
	 */
	public boolean setWidth( final float value )
	{
		if( this.mDrawingElementArray==null )
		{
			return true;
		}

		SGDrawingElement[] array = this.mDrawingElementArray;
		for( int ii=0; ii<array.length; ii++ )
		{
			SGDrawingElementBar2D bar = (SGDrawingElementBar2D)array[ii];
			bar.setWidth(value);
		}

		return true;
	}


	/**
	 * 
	 * @param value
	 * @return
	 */
	public boolean setHeight( final float value )
	{
		if( this.mDrawingElementArray==null )
		{
			return true;
		}

		SGDrawingElement[] array = this.mDrawingElementArray;
		for( int ii=0; ii<array.length; ii++ )
		{
			SGDrawingElementBar2D bar = (SGDrawingElementBar2D)array[ii];
			bar.setHeight(value);
		}

		return true;
	}


	/**
	 * 
	 * @param b
	 * @return
	 */
	public boolean setHorizontal( final boolean b )
	{
		if( this.mDrawingElementArray==null )
		{
			return true;
		}

		SGDrawingElement[] array = this.mDrawingElementArray;
		for( int ii=0; ii<array.length; ii++ )
		{
			SGDrawingElementBar2D bar = (SGDrawingElementBar2D)array[ii];
			bar.setHorizontal(b);
		}

		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setPropertiesOfDrawingElements()
	{
		SGDrawingElement[] array = this.mDrawingElementArray;
		for( int ii=0; ii<array.length; ii++ )
		{
			SGDrawingElementBar2D bar
				= (SGDrawingElementBar2D)array[ii];
			bar.setMagnification( this.mMagnification );
			bar.setColor( this.mColorList );
			bar.setEdgeLineWidth( this.mEdgeLineWidth );
			bar.setEdgeLineColor( this.mEdgeLineColor );
		}
		return true;
	}



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


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

		super.getProperties(p);

		BarProperties bp = (BarProperties)p;
//		bp.setBarWidth( this.getRectangleWidth() );
		bp.setEdgeLineWidth( this.getEdgeLineWidth() );
		bp.setEdgeLineColor( this.getEdgeLineColor() );
		bp.setBaselineValue( this.getBaselineValue() );
		bp.setWidthValue( this.getWidthValue() );

		return true;
	}


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

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

		BarProperties bp = (BarProperties)p;

// for the versions older than 0.9.1
Float width = bp.getBarWidth();
if( width==null )
{
	return false;
}
this.setRectangleWidth( width.floatValue() );

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

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

		Double baselineValue = bp.getBaselineValue();
		if( baselineValue==null )
		{
			return false;
		}
		this.setBaselineValue( baselineValue.doubleValue() );

		Double widthValue = bp.getWidthValue();
		if( widthValue==null )
		{
			return false;
		}
		this.setWidthValue( widthValue.doubleValue() );

		return true;
	}




	/**
	 * 
	 */
	public static class BarProperties extends ElementGroupProperties
	{
		private SGDrawingElementBar.BarProperties mBarProperties
			= new SGDrawingElementBar.BarProperties();


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


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

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

			BarProperties p = (BarProperties)obj;

			if( this.mBarProperties.equals( p.mBarProperties ) == false ) return false;

			return true;
		}



		public Float getBarWidth()
		{
			return this.mBarProperties.getWidth();
		}

		public Float getEdgeLineWidth()
		{
			return this.mBarProperties.getEdgeLineWidth();
		}

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

		public Double getBaselineValue()
		{
			return this.mBarProperties.getBaselineValue();
		}

		public Double getWidthValue()
		{
			return this.mBarProperties.getWidthValue();
		}


		public void setBarWidth( final float width )
		{
			this.mBarProperties.setWidth( width );
		}


		public void setBaselineValue( final double value )
		{
			this.mBarProperties.setBaselineValue( value );
		}

		public void setWidthValue( final double value )
		{
			this.mBarProperties.setWidthValue( value );
		}

		public void setEdgeLineWidth( final float width )
		{
			this.mBarProperties.setEdgeLineWidth( width );
		}

		public void setEdgeLineColor( final Color cl )
		{
			this.mBarProperties.setEdgeLineColor(cl);
		}

	}

}

