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

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
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.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.SGDrawingElementSymbol;
import jp.riken.brain.ni.samuraigraph.figure.SGISymbolConstants;

import org.w3c.dom.Element;



/**
 * 
 */
public abstract class SGElementGroupSymbol extends SGElementGroupSXY
	implements SGISymbolConstants, SGIElementGroupConstants
{

	/**
	 *
	 */
	protected float mSymbolSize;


	/**
	 *
	 */
	protected int mSymbolType;


	/**
	 * 
	 */
	protected double mAngle;


	/**
	 * 
	 */
	protected Color mLineColor;

		
	/**
	 * 
	 */
	protected float mLineWidth;



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


	/**
	 * 
	 */
	public void dispose()
	{
		super.dispose();

		this.mLineColor = null;
	}


	/**
	 * 
	 */
	public float getSize()
	{
		return this.mSymbolSize;
	}


	/**
	 * 
	 * @param unit
	 * @return
	 */
	public float getSize( final String unit )
	{
		return (float)SGUtilityText.convertFromPoint( this.getSize(), unit );
	}


	/**
	 * 
	 */
	public int getType()
	{
		return this.mSymbolType;
	}


	/**
	 * 
	 */
	public double getAngle()
	{
		return this.mAngle;
	}


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


	/**
	 * 
	 * @param unit
	 * @return
	 */
	public float getLineWidth( final String unit )
	{
		return (float)SGUtilityText.convertFromPoint( this.getLineWidth(), unit );
	}


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


	/**
	 *
	 */
	public boolean setSize( final float size )
	{
		mSymbolSize = size;
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				SGDrawingElementSymbol2D el = (SGDrawingElementSymbol2D)mDrawingElementArray[ii];
				el.setSize(mSymbolSize);
			}
		}

		return true;
	}


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

		return true;
	}


	/**
	 *
	 */
	public boolean setType( final int type )
	{
		mSymbolType = type;
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				SGDrawingElementSymbol2D el = (SGDrawingElementSymbol2D)mDrawingElementArray[ii];
				el.setType(mSymbolType);
			}
		}
		return true;
	}


	/**
	 *
	 */
	public boolean setLineColor( final Color color )
	{
		mLineColor = color;
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				SGDrawingElementSymbol2D el = (SGDrawingElementSymbol2D)mDrawingElementArray[ii];
				el.setLineColor(mLineColor);
			}
		}
		return true;
	}


	/**
	 * 
	 */
	public boolean setLineColor( final String value )
	{
		final Color cl = SGUtilityText.getColor(value);
		if( cl==null )
		{
			return false;
		}
		else
		{
			return this.setLineColor(cl);
		}
	}


	/**
	 * 
	 * @param r
	 * @param g
	 * @param b
	 * @return
	 */
	public boolean setLineColor( final String r, final String g, final String b )
	{
		final Color cl = SGUtilityText.getColor(r,g,b);
		if( cl==null )
		{
			return false;
		}
		else
		{
			return this.setLineColor(cl);
		}
	}


	/**
	 *
	 */
	public boolean setLineWidth( final float width )
	{
		mLineWidth = width;
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				SGDrawingElementSymbol2D el = (SGDrawingElementSymbol2D)mDrawingElementArray[ii];
				el.setLineWidth(mLineWidth);
			}
		}
		return true;
	}


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


	/**
	 * 
	 */
	public SGDrawingElement getDrawingElement()
	{
		SGDrawingElementSymbol symbol
			= (SGDrawingElementSymbol)this.getDrawingElementInstance();
		symbol.setVisible( this.isVisible() );
		symbol.setSize( this.getSize() );
		symbol.setType( this.getType() );	
		symbol.setColor( this.getColorList() );
		symbol.setLineColor( this.getLineColor() );
		symbol.setLineWidth( this.getLineWidth() );

		return symbol;
	}


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

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

		SGDrawingElementSymbol symbol = (SGDrawingElementSymbol)element;

		this.setType( symbol.getType() );
		this.setSize( symbol.getSize() );
		this.setLineWidth( symbol.getLineWidth() );
		this.setLineColor( symbol.getLineColor() );
	
		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++ )
			{
				SGDrawingElementSymbol2D el
					= (SGDrawingElementSymbol2D)array[ii];
				if( el.isVisible() == false )
				{
					continue;
				}

				el.paint( g2d, clipRect );
			}
		}

		return true;
	}




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


	/**
	 * 
	 */
	public boolean writeProperty( final Element el )
	{
		final String cm = SGUtilityNumber.cm;
		final String pt = SGUtilityNumber.pt;
		el.setAttribute( KEY_SYMBOL_SIZE, Float.toString( this.mSymbolSize*SGIConstants.CM_POINT_RATIO ) + cm );
		el.setAttribute( KEY_SYMBOL_TYPE, SGDrawingElementSymbol.getSymbolTypeName( this.mSymbolType ) );
		el.setAttribute( KEY_SYMBOL_INNER_COLOR_LIST, SGUtilityText.getColorListString( this.mColorList ) );
		el.setAttribute( KEY_SYMBOL_LINE_WIDTH, Float.toString( this.mLineWidth ) + pt );
		el.setAttribute( KEY_SYMBOL_LINE_COLOR, SGUtilityText.getColorString( this.mLineColor ) );
		return true;
	}

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

		// symbol size
		str = el.getAttribute( KEY_SYMBOL_SIZE );
		if( str.length()!=0 )
		{
			StringBuffer uSize = new StringBuffer();
			num = SGUtilityText.getNumber( str, uSize );
			if( num==null )
			{
				return false;
			}
			final float size = num.floatValue();
			if( this.setSize( size, uSize.toString() ) == false )
			{
				return false;
			}
		}


		// symbol type
		str = el.getAttribute( KEY_SYMBOL_TYPE );
		if( str.length()!=0 )
		{
			num = SGDrawingElementSymbol.getSymbolTypeFromName(str);
			if( num==null )
			{
				return false;
			}
			final int type = num.intValue();
			if( this.setType( type ) == false )
			{
				return false;
			}
		}


		// inner color
		str = el.getAttribute( KEY_SYMBOL_INNER_COLOR_LIST );
		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;
			}
		}


		// line width
		str = el.getAttribute( KEY_SYMBOL_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;
			}
		}


		// line color
		str = el.getAttribute( KEY_SYMBOL_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;
			}
		}


		return true;
	}



	/**
	 * 
	 * @return
	 */
	protected SGDrawingElement getDrawingElementInstance()
	{
		return new SGDrawingElementSymbol2D();
	}



	/**
	 * 
	 * @return
	 */
	protected boolean initDrawingElement( final SGTuple2f[] array )
	{
		final int num = array.length;
		this.initDrawingElement(num);

		SGDrawingElement[] sArray = this.mDrawingElementArray;
		for( int ii=0; ii<num; ii++ )
		{
			((SGDrawingElementSymbol)sArray[ii]).setLocation( array[ii] );
		}
		return true;
	}


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

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


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


		// シンボルの描画要素を作成
		for( int ii=0; ii<pointArray.length; ii++ )
		{
			SGDrawingElementSymbol2D symbol
				= (SGDrawingElementSymbol2D)this.mDrawingElementArray[ii];
			final boolean eff = !( pointArray[ii].isInfinite() || pointArray[ii].isNaN() );
			symbol.setVisible( eff );
			if( eff )
			{
				symbol.setLocation( pointArray[ii] );
			}
		}

		return true;
	}



	/**
	 * 
	 * @return
	 */
	public boolean setPropertiesOfDrawingElements()
	{
		for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
		{
			SGDrawingElementSymbol2D symbol
				= (SGDrawingElementSymbol2D)this.mDrawingElementArray[ii];
			symbol.setMagnification(mMagnification);
			symbol.setColor( this.mColorList );
			symbol.setSize( this.mSymbolSize );
			symbol.setType( this.mSymbolType );
			symbol.setLineWidth( this.mLineWidth );
			symbol.setLineColor( this.mLineColor );
		}
		return true;
	}


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


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

		super.getProperties(p);

		SymbolProperties sp = (SymbolProperties)p;
		sp.setSize( this.getSize() );
		sp.setSymbolType( this.getType() );
		sp.setLineWidth( this.getLineWidth() );
		sp.setLineColor( this.getLineColor() );

		return true;
	}


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

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

		final Float size = sp.getSize();
		if( size==null )
		{
			return false;
		}
		this.setSize( size.floatValue() );

		final Integer type = sp.getSymbolType();
		if( type==null )
		{
			return false;
		}
		this.setType( type.intValue() );

		final Float lineWidth = sp.getLineWidth();
		if( lineWidth==null )
		{
			return false;
		}
		this.setLineWidth( lineWidth.floatValue() );

		final Color lineColor = sp.getLineColor();
		if( lineColor==null )
		{
			return false;
		}
		this.setLineColor( lineColor );

		return true;
	}





	/**
	 * 
	 */
	public static class SymbolProperties extends ElementGroupProperties
	{
		private SGDrawingElementSymbol.SymbolProperties mSymbolProperties
			= new SGDrawingElementSymbol.SymbolProperties();


//		public static final String[] keys = {
//			KEY_SYMBOL_TYPE, KEY_SYMBOL_SIZE,
//			KEY_LINE_WIDTH, KEY_LINE_COLOR
//		};



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


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

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

			SymbolProperties p = (SymbolProperties)obj;

			if( this.mSymbolProperties.equals(p.mSymbolProperties) == false ) return false;
			
//			for( int ii=0; ii<keys.length; ii++ )
//			{
//				if( this.getProperty(keys[ii]).equals(p.getProperty(keys[ii])) == false )
//				{
//					return false;
//				}
//			}
//			if( p.angle != this.angle ) return false;

			return true;
		}


		public Float getSize()
		{
			return this.mSymbolProperties.getSize();
//			final String value = this.getProperty(KEY_SYMBOL_SIZE);
//			return SGUtilityText.getFloat(value);
		}

		public Integer getSymbolType()
		{
			return this.mSymbolProperties.getSymbolType();
//			final String value = this.getProperty(KEY_SYMBOL_TYPE);
//			return SGUtilityText.getInteger(value);
		}

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

		public Color getLineColor()
		{
			return this.mSymbolProperties.getLineColor();
//			final String value = this.getProperty(KEY_LINE_COLOR);
//			return SGUtilityText.getColorFromString(value);
		}


		public void setSize( final float size )
		{
			this.mSymbolProperties.setSize(size);
//			if( size<0.0f )
//			{
//				return false;
//			}
//			this.setProperty( KEY_SYMBOL_SIZE, new Float(size).toString() );
//			return true;
		}


		public void setSymbolType( final int type )
		{
			this.mSymbolProperties.setSymbolType( type );
//			this.setProperty( KEY_SYMBOL_TYPE, new Integer(type).toString() );
//			return true;
		}


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

		public void setLineColor( final Color cl )
		{
			this.mSymbolProperties.setLineColor( cl );
//			if( cl==null )
//			{
//				return false;
//			}
//			String str = SGUtilityText.getColorString(cl);
//			if( str==null )
//			{
//				return false;
//			}
//			this.setProperty( KEY_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("type="+type+", ");
			str += new String("size="+size+", ");
			str += new String("edgeLineWidth="+edgeLineWidth+", ");
			str += new String("edgeLineColor="+edgeLineColor+", ");
			str += new String("angle="+angle+", ");
			str += new String("]");

			return str;
		}
*/

	}



}
