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

import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import jp.riken.brain.ni.samuraigraph.base.*;
import jp.riken.brain.ni.samuraigraph.data.*;
import jp.riken.brain.ni.samuraigraph.figure.*;


/**
 *
 */
public abstract class SGElementGroupBar extends SGElementGroupRectangle
{


	/**
	 * 
	 */
	protected double mBaselineValue = 0.0;



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



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


	/**
	 * 
	 */
	public boolean setBaseLineValue( final double value )
	{
		this.mBaselineValue = 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.getReferenceValue() );

		return true;
	}



	/**
	 * 
	 */
	public boolean paintElement( final Graphics2D g2d )
	{

		ArrayList colorList = new ArrayList(this.mColorList);
		if( this.mEnteredFlag )
		{
			ArrayList colorList_ = new ArrayList();
			for( int ii=0; ii<colorList.size(); ii++ )
			{
				Color colorOld = ((Color)colorList.get(ii));
/*		Color color_ = new Color(
			255 - colorOld.getRed(),
			255 - colorOld.getGreen(),
			255 - colorOld.getBlue()
		);
*/
				Color color_ = new Color(
					colorOld.getRed(),
					colorOld.getGreen(),
					colorOld.getBlue(),
					128
				);
				colorList_.add(color_);
			}
			this.setColorList(colorList_);
		}


		if( this.mSelectedFlag )
		{
//			this.shiftColorList();
		}



		float width = (float)(mMagnification*this.mEdgeLineWidth);

		for( int ii=0; ii<this.mDrawingElementList.size(); ii++ )
		{
			SGDrawingElementBar2D el
				= (SGDrawingElementBar2D)mDrawingElementList.get(ii);

			double x = (el.getX());
			double y = (el.getY());
			double w = (el.getWidth());
			double h = (el.getHeight());

			Rectangle2D dRect = new Rectangle2D.Double( x, y, w, h );

			// fill the rectangles
			int cNum = this.mColorList.size();
			if( cNum > 1 )
			{
				//
				// 複数の色を持つ場合には、GradientPaintを用いる
				//

				// X座標値
				float gX = (float)( ( x + 0.50*w ) );

				// 高さを色数で割った値
				float diff = (float)(h)/(float)cNum;

				// グラデーションを付ける幅
//				float delta = diff/10.0f;
float delta = 5.0f;

				// rectangleを分割する（色数+1）
				Rectangle2D[] rectArray = new Rectangle2D[cNum+1];
				rectArray[0] = new Rectangle2D.Double( x, y, w, 0.50*diff );	// 上端
				rectArray[rectArray.length-1]
					= new Rectangle2D.Double(
						x, (y+h-0.50*diff), w, 0.50*diff );		// 下端
				for( int jj=1; jj<rectArray.length-1; jj++ )
				{
					double yy = y+ 0.50*diff + (double)(jj-1)*diff;
					rectArray[jj] = new Rectangle2D.Double(
						x, yy, w, diff );
				}


				// 区切り点のY座標値の配列（色数-1）
				float[] gYArray = new float[cNum-1];
				for( int jj=0; jj<gYArray.length; jj++ )
				{
					gYArray[jj] = (float)( ( y + (jj+1)*diff ) );
				}


				// 分割した矩形を塗りつぶす
				g2d.setPaint( (Color)this.getColorList().get(0) );
				g2d.fill(rectArray[0]);

				for( int jj=0; jj<gYArray.length; jj++ )
				{
					Color c1 = (Color)this.mColorList.get(jj);
					Color c2 = (Color)this.mColorList.get(jj+1);
					float y1 = gYArray[jj] - delta;
					float y2 = gYArray[jj] + delta;
					GradientPaint gPaint = new GradientPaint(
						gX, y1, c1, gX, y2, c2 );

					g2d.setPaint( gPaint );
					g2d.fill(rectArray[jj+1]);
				}

				g2d.setPaint( (Color)this.getColorList().get(cNum-1) );
				g2d.fill(rectArray[rectArray.length-1]);


			}
			else
			{
				g2d.setPaint(this.getColor(0));
				g2d.fill(dRect);
			}



			// draw edge lines
			g2d.setStroke(
				new BasicStroke
				(
					width,
					BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER
				)
			);
			g2d.setPaint(this.mEdgeLineColor);
			g2d.draw(dRect);

		}


		this.setColorList(colorList);

		return true;
	}



	/**
	 * 
	 */
	public SGDrawingElement getDrawingElement()
	{
		SGDrawingElementBar rect = new SGDrawingElementBar2D();
		rect.setWidth( this.mRectangleWidth );
		rect.setHeight( this.mRectangleHeight );
		rect.setEdgeLineWidth( this.mEdgeLineWidth );
		rect.setEdgeLineColor( this.mEdgeLineColor );
		rect.setColorList( this.mColorList );
		rect.setReferenceValue( this.mBaselineValue );

		return rect;
	}


	public static final String BAR_TITLE = "<Bar>";
	public static final String KEY_BAR_WIDTH = "Width";
	public static final String KEY_EDGE_LINE_WIDTH = "Edge Line Width";
	public static final String KEY_EDGE_LINE_COLOR = "Edge Line Color";
	public static final String KEY_BASELINE_VALUE = "Baseline Value";


	/**
	 * 
	 */
	public boolean writePropertyOfData( final Writer writer ) throws IOException
	{

		writer.write( BAR_TITLE + "\n" );

		SGUtilityText.writePropertyLine( writer, KEY_VISIBLE, new Boolean( this.mVisibleFlag ) );
		SGUtilityText.writePropertyLine( writer, KEY_BAR_WIDTH, new Float( this.mRectangleWidth*this.mRulerUnit ) );
		SGUtilityText.writeColorListPropertyLine( writer, KEY_COLOR_LIST, this.mColorList );
		SGUtilityText.writePropertyLine( writer, KEY_EDGE_LINE_WIDTH, new Float( this.mEdgeLineWidth ) );
		SGUtilityText.writePropertyLine( writer, KEY_BASELINE_VALUE, new Double( this.mBaselineValue ) );
		SGUtilityText.writeColorPropertyLine( writer, KEY_EDGE_LINE_COLOR, this.mEdgeLineColor );

		writer.write("\n");

		return true;
	}



	/**
	 * 
	 */
	public SGProperties readProperties( final BufferedReader br ) throws IOException
	{
		BarProperties p = new BarProperties();

		String line = null;


		// visible
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Boolean bVisible = SGUtilityText.getBooleanPropertyFromLine(line,KEY_VISIBLE);
		if( bVisible == null )
		{
			return null;
		}
		p.setVisible( bVisible.booleanValue() );


		// width of the bar
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dBarWidth = SGUtilityText.getDoublePropertyFromLine(line,KEY_BAR_WIDTH);
		if( dBarWidth == null )
		{
			return null;
		}
		p.setBarWidth( dBarWidth.floatValue()/SGConstants.CM_POINT_RATIO );


		// inner color list
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		ArrayList colorList = SGUtilityText.getColorListFromLine(line,KEY_COLOR_LIST);
		if( colorList == null )
		{
			return null;
		}
		p.setColorList( colorList );


		// edge line width
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dEdgeLineWidth = SGUtilityText.getDoublePropertyFromLine(line,KEY_EDGE_LINE_WIDTH);
		if( dEdgeLineWidth == null )
		{
			return null;
		}
		p.setEdgeLineWidth( dEdgeLineWidth.floatValue() );


		// baseline value
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Double dBaselineValue = SGUtilityText.getDoublePropertyFromLine(line,KEY_BASELINE_VALUE);
		if( dBaselineValue == null )
		{
			return null;
		}
		p.setBaselineValue( dBaselineValue.doubleValue() );


		// edge line color
		if( ( line = SGUtilityText.readLine(br) ) == null )
		{
			return null;
		}
		Color edgeLineColor = SGUtilityText.getColorPropertyFromLine(line,KEY_EDGE_LINE_COLOR);
		if( edgeLineColor == null )
		{
			return null;
		}
		p.setEdgeLineColor( edgeLineColor );


		return p;

	}



	/**
	 * 
	 */
	public boolean createDrawingElement(
		final ArrayList pointList )
	{

		mDrawingElementList.clear();

		// 棒グラフの描画要素を作成
		for( int ii=0; ii<pointList.size(); ii++ )
		{
			SGTuple2f point = (SGTuple2f)pointList.get(ii);
			SGDrawingElementBar2D rect
				= new SGDrawingElementBar2D(
					point.x, point.y,
					this.mRectangleWidth, this.mRectangleHeight );
			rect.setColorList( mColorList );
			this.addDrawingElement(rect);
		}


		return true;
	}


	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		BarProperties p = new BarProperties();
		this.getProperties(p);
		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() );

		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;

		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() );

		return true;
	}




	/**
	 * 
	 */
	public static class BarProperties extends ElementGroupProperties
	{
//		float width;
//		float edgeLineWidth;
//		Color edgeLineColor;
//		double baselineValue;


		public static final String[] keys = {
			KEY_BAR_WIDTH, KEY_EDGE_LINE_WIDTH, KEY_EDGE_LINE_COLOR, KEY_BASELINE_VALUE
		};


		/**
		 * 
		 */
		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;
			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 getBarWidth()
		{
			final String value = this.getProperty(KEY_BAR_WIDTH);
			return SGUtilityText.getFloat(value);
		}

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

		public Color getEdgeLineColor()
		{
			final String value = this.getProperty(KEY_EDGE_LINE_COLOR);
			return SGUtilityText.getColorFromString(value);
		}

		public Double getBaselineValue()
		{
			final String value = this.getProperty(KEY_BASELINE_VALUE);
			return SGUtilityText.getDouble(value);
		}


		public boolean setBarWidth( final float width )
		{
			if( width<0.0f )
			{
				return false;
			}
			this.setProperty( KEY_BAR_WIDTH, new Float(width).toString() );
			return true;
		}


		public boolean setBaselineValue( final double value )
		{
			this.setProperty( KEY_BASELINE_VALUE, new Double(value).toString() );
			return true;
		}


		public boolean setEdgeLineWidth( final float width )
		{
			if( width<0.0f )
			{
				return false;
			}
			this.setProperty( KEY_EDGE_LINE_WIDTH, new Float(width).toString() );
			return true;
		}

		public boolean setEdgeLineColor( final Color cl )
		{
			if( cl==null )
			{
				return false;
			}
			String str = SGUtilityText.getColorString(cl);
			if( str==null )
			{
				return false;
			}
			this.setProperty( KEY_EDGE_LINE_COLOR, str );
			return true;
		}





		/**
		 * 
		 */
/*		public String toString()
		{
			String str = new String("[");
			str += new String("visible="+visible+", ");
			str += new String("colorList="+colorList+", ");
			str += new String("width="+width+", ");
			str += new String("edgeLineWidth="+edgeLineWidth+", ");
			str += new String("edgeLineColor="+edgeLineColor+", ");
			str += new String("baselineValue="+baselineValue+", ");
			str += new String("]");

			return str;
		}
*/
	}

}
