
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.SGProperties;
import jp.riken.brain.ni.samuraigraph.base.SGTuple2f;

import org.w3c.dom.Document;
import org.w3c.dom.Element;



/**
 * 描画要素のグループの基本クラス
 * 描画要素(SGDrawingElement)のリストを持つ
 */
public abstract class SGElementGroup implements SGIElementGroupConstants
{

	/**
	 * 描画要素(SGDrawingElement)の配列
	 */
	protected SGDrawingElement[] mDrawingElementArray = null;



	/**
	 * ElementGroupSetへの参照
	 */
	protected SGElementGroupSet mGroupSet = null;



	/**
	 * 
	 */
	protected float mMagnification = 1.0f;



	/**
	 * 
	 */
	protected ArrayList mColorList = new ArrayList();



	/**
	 * 
	 */
	protected boolean mVisibleFlag = true;



	/**
	 * 
	 * @return
	 */
	public SGElementGroup()
	{
	}



	/**
	 * 
	 * @return
	 */
	protected abstract boolean initDrawingElement( final int num );


	/**
	 * 
	 * @return
	 */
	protected boolean initDrawingElement( final SGTuple2f[] array )
	{
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public boolean setPropertiesOfDrawingElements()
	{
		return true;
	}


	/**
	 * 
	 */
	protected boolean setDialogProperty()
	{
		return true;
	}


	/**
	 * 
	 * @return
	 */
	public float getMagnification()
	{
		return this.mMagnification;
	}


	/**
	 * 
	 */
	public boolean setMagnification( final float ratio )
	{
		if( ratio < 0.0 )
		{
			throw new IllegalArgumentException("ratio < 0.0");
		}
		mMagnification = ratio;
		
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				this.mDrawingElementArray[ii].setMagnification(ratio);
			}
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean addColor( final Color color )
	{
		if( color==null )
		{
			throw new IllegalArgumentException("color==null");
		}
		mColorList.add(color);

		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				this.mDrawingElementArray[ii].addColor( color );
			}
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean setColor( final Color color )
	{
		if( color==null )
		{
			throw new IllegalArgumentException("color==null");
		}

		mColorList.clear();
		mColorList.add(color);
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				this.mDrawingElementArray[ii].setColor( color );
			}
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean setColorList( final ArrayList colorList )
	{
		if( colorList==null )
		{
			throw new IllegalArgumentException("colorList==null");
		}
		if( colorList.size()==0 )
		{
			throw new IllegalArgumentException("colorList.size()==0");
		}

		mColorList = new ArrayList(colorList);
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				this.mDrawingElementArray[ii].setColor( colorList );
			}
		}
		
		return true;
	}


	/**
	 * 
	 */
	public Color getColor( final int index )
	{
		if( mColorList == null )
		{
			return null;
		}

		if( index >= mColorList.size() )
		{
			new ArrayIndexOutOfBoundsException("index >= mColorList.size()");
		}

		return (Color)mColorList.get(index);
	}


	/**
	 * 
	 */
	public ArrayList getColorList()
	{
		return mColorList;
	}



	/**
	 * 
	 */
	public boolean zoom( float ratio )
	{
		this.mMagnification = ratio;
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				this.mDrawingElementArray[ii].zoom(ratio);
			}
		}

		return true;
	}



	/**
	 * 
	 */
	public void setVisible( final boolean flag )
	{
		this.mVisibleFlag = flag;
	}


	/**
	 * 
	 */
	public boolean isVisible()
	{
		return this.mVisibleFlag;
	}


	/**
	 * 
	 */
	public boolean contains( final int x, final int y )
	{
		if( this.mDrawingElementArray!=null )
		{
			for( int ii=0; ii<this.mDrawingElementArray.length; ii++ )
			{
				if( this.mDrawingElementArray[ii].isVisible() == false )
				{
					continue;
				}
				if( this.mDrawingElementArray[ii].contains(x,y) )
				{
					return true;
				}
			}
		}
		return false;
	}




	/**
	 * 
	 */
	public boolean paintElement( final Graphics2D g2d )
	{
		return this.paintElement( g2d, null );
	}



	/**
	 * 
	 */
	public abstract boolean paintElement(
		final Graphics2D g2d, final Rectangle2D clipRect );


	/**
	 * 
	 */
	public abstract SGDrawingElement getDrawingElement();


	/**
	 * 
	 */
	public boolean setProperty( final SGDrawingElement element )
	{
		this.setVisible( element.isVisible() );
		this.setColorList( element.getColorList() );

		return true;
	}


	
	/**
	 * 
	 * @return
	 */
	public abstract String getTagName();


	/**
	 * 
	 * @param document
	 * @return
	 */
	public Element createElement( final Document document )
	{
		Element el = document.createElement( this.getTagName() );
		if( this.writeProperty(el) == false )
		{
			return null;
		}
		return el;
	}
	
	
	/**
	 * 
	 */
	public abstract boolean writeProperty( final Element el );


	/**
	 * 
	 */
	public boolean readProperty( final Element el )
	{
		SGProperties p = this.readProperties( el );
		if( this.setProperties(p) == false ) return false;
		return true;
	}

	
	/**
	 * 
	 * @param el
	 * @return
	 */
	public abstract SGProperties readProperties( final Element el );

	

	/**
	 * 
	 */
	public boolean setPropertyWithDialog()
	{
		if( this.setProperties( this.getPropertiesFromDialog() ) == false ) return false;

		return true;

	}



	/**
	 * 
	 */
	public SGProperties getProperties()
	{
		ElementGroupProperties p = new ElementGroupProperties();
		this.getProperties(p);

		return p;
	}


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

		ElementGroupProperties ep = (ElementGroupProperties)p;

		ep.setVisible( this.isVisible() );
		ep.setColorList( new ArrayList( this.mColorList ) );

		return true;
	}


	/**
	 * 
	 */
	protected ElementGroupProperties getPropertiesFromDialog()
	{
		return null;
	}



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

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

		ElementGroupProperties ep = (ElementGroupProperties)p;

		final Boolean b = ep.isVisible();
		if( b==null )
		{
			return false;
		}

		final ArrayList cList = ep.getColorList();
		if( cList==null )
		{
			return false;
		}

		this.setVisible( b.booleanValue() );
		this.setColorList( cList );

		return true;		
	}


	/**
	 * 
	 */
	public static class ElementGroupProperties extends SGProperties
	{
		private boolean mVisible;
		private ArrayList mColorList = new ArrayList();

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

		/**
		 * 
		 */
		public boolean equals( final Object obj )
		{

			if( ( obj instanceof ElementGroupProperties ) == false ) return false;

			ElementGroupProperties p = (ElementGroupProperties)obj;

			if( this.mVisible!=p.mVisible ) return false;
			if( this.mColorList.equals(p.mColorList) == false ) return false;

			return true;
		}


		public Boolean isVisible()
		{
			return Boolean.valueOf( this.mVisible );
		}

		public ArrayList getColorList()
		{
			return new ArrayList( this.mColorList );
		}

		public void setVisible( final boolean b )
		{
			this.mVisible = b;
		}

		public void setColorList( final ArrayList list )
		{
			if( list==null )
			{
				throw new IllegalArgumentException("list==null");
			}
			
			this.mColorList = new ArrayList(list);
		}

	}



}

