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

import java.awt.Graphics2D;
import java.util.ArrayList;

import jp.riken.brain.ni.samuraigraph.base.SGDrawingElement;
import jp.riken.brain.ni.samuraigraph.base.SGIVisible;
import jp.riken.brain.ni.samuraigraph.base.SGProperties;

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



/**
 * 描画要素グループのセットのクラス
 */
public abstract class SGElementGroupSet implements SGIVisible
{


	/**
	 * 描画要素グループ(SGElementGroup)のリスト
	 */
	protected ArrayList mDrawingElementGroupList = new ArrayList();


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


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



	/**
	 * 
	 */
	public SGElementGroupSet()
	{
	}



	/**
	 * 
	 */
	public ArrayList getDrawingElementList()
	{
		ArrayList list = new ArrayList();
		ArrayList groupList = new ArrayList( this.mDrawingElementGroupList );
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)groupList.get(ii);
			SGDrawingElement dElement = group.getDrawingElement();
			list.add( dElement );
		}

		return list;
	}



	/**
	 * 
	 */
	public boolean moveElementsToFront( final SGElementGroup group )
	{
		ArrayList groupList = this.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			if( group.equals(groupList.get(ii)) )
			{
				groupList.remove(ii);
				break;
			}
		}
		groupList.add(groupList.size(),group);

		return true;
	}


	/**
	 * 
	 */
	public boolean moveElementsToBack( final SGElementGroup group )
	{
		ArrayList groupList = this.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			if( group.equals(groupList.get(ii)) )
			{
				groupList.remove(ii);
				break;
			}
		}
		groupList.add(0,group);

		return true;
	}


	/**
	 * 
	 */
	public boolean removeElements( final SGElementGroup group )
	{
		ArrayList groupList = this.mDrawingElementGroupList;
		for( int ii=0; ii<groupList.size(); ii++ )
		{
			if( group.equals(groupList.get(ii)) )
			{
				groupList.remove(ii);
				return true;
			}
		}

		return false;
	}



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


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



	/**
	 * 
	 */
	public boolean setMagnification( final float mag )
	{

		this.mMagnification = mag;

		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			group.setMagnification(mag);
		}

		return true;
	}



	/**
	 * 
	 */
	public boolean zoom( final float ratio )
	{

		this.mMagnification = ratio;

		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			group.zoom(ratio);
		}

		return true;
	}



	/**
	 * 
	 */
	public abstract boolean addDrawingElementGroup( final int type );


	/**
	 * 
	 */
	public abstract void paintGraphics2D( final Graphics2D g2d );


	/**
	 * 
	 */
	public boolean contains( final int x, final int y )
	{
		ArrayList list = this.mDrawingElementGroupList;
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			SGElementGroup group = (SGElementGroup)list.get(ii);
			if( group.isVisible() == false )
			{
				continue;
			}

			if( group.contains(x,y) )
			{
				return true;
			}
		}

		return false;
	}


	/**
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public SGElementGroup getElementGroupAt( final int x, final int y )
	{
		ArrayList list = this.mDrawingElementGroupList;
		for( int ii=list.size()-1; ii>=0; ii-- )
		{
			SGElementGroup group = (SGElementGroup)list.get(ii);
			if( group.isVisible() == false )
			{
				continue;
			}
			if( group.contains( x, y ) )
			{
				return group;
			}
		}		

		return null;
	}


//	/**
//	 * 
//	 */
//	public abstract boolean addDrawingElementGroup( final SGDrawingElement element );



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


	/**
	 * 
	 */
	public abstract boolean writeProperty( final Element el );


	/**
	 * 
	 * @param document
	 * @return
	 */
	public Element createElement( final Document document )
	{
		Element el = document.createElement( this.getTagName() );
		if( this.writeProperty(el) == false )
		{
			return null;
		}
		
		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			String tagName = group.getTagName();
			Element elGroup = document.createElement(tagName);
			if( group.writeProperty(elGroup) == false )
			{
				return null;
			}
			el.appendChild(elGroup);
		}
		return el;
	}

	
	/**
	 * 
	 */
	public abstract boolean onDrawingElement( final int x, final int y );



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

		ElementGroupSetProperties ep = (ElementGroupSetProperties)p;
		
		this.setVisible( ep.visible );

		return true;
	}


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


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

		ElementGroupSetProperties gp = (ElementGroupSetProperties)p;
		gp.visible = this.isVisible();

		return true;
	}




	/**
	 * 
	 */
	public SGProperties getWholeProperties()
	{
		WholeProperties wp = new WholeProperties();
		if( this.getWholeProperties(wp) == false ) return null;
		return wp;
	}


	/**
	 * 
	 */
	public boolean getWholeProperties( final SGProperties p )
	{
		if( ( p instanceof WholeProperties ) == false ) return false;

		WholeProperties wp = (WholeProperties)p;
		wp.ep = (ElementGroupSetProperties)this.getProperties();
		(wp.ipList).clear();
		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			(wp.ipList).add( group.getProperties() );
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean setWholeProperties( final SGProperties p )
	{
		if( ( p instanceof WholeProperties ) == false ) return false;

		WholeProperties wp = (WholeProperties)p;

		if( this.setProperties( wp.ep ) == false ) return false;

		ArrayList list = wp.ipList;
		for( int ii=0; ii<list.size(); ii++ )
		{
			SGProperties ep = (SGProperties)list.get(ii);
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			if( group.setProperties(ep) == false ) return false;
		}

		return true;
	}



	/**
	 * 
	 */
	public static class WholeProperties extends SGProperties
	{

		ElementGroupSetProperties ep;
		ArrayList ipList = new ArrayList();


		public WholeProperties()
		{
			super();
		}


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

			if( ( obj instanceof WholeProperties ) == false )
			{
				return false;
			}

			WholeProperties p = (WholeProperties)obj;

			if( p.ep.equals(this.ep) == false )
			{
//System.out.println("eq");
				return false;
			} 


			if( p.ipList.equals(this.ipList) == false )
			{
//System.out.println("ipList");
//System.out.println(p.ipList);
//System.out.println(this.ipList);
//System.out.println();
				return false;
			} 

/*
for( int ii=0; ii<this.ipList.size(); ii++ )
{
	Object obj1 = this.ipList.get(ii);
	Object obj2 = p.ipList.get(ii);
	boolean flag = obj1.equals(obj2);
	System.out.println("ii="+ii+" "+flag );
	if( !flag )
	{
		System.out.println(obj1);
		System.out.println(obj2);
		System.out.println();
	}
}
*/

			return true;

		}


		/**
		 * 
		 */
		public String toString()
		{
			String str = new String("[");
			str += this.ep.toString();
			str += this.ipList.toString();
			str += new String("]");

			return str;
		}


	}




	/**
	 * 
	 */
	public static class ElementGroupSetProperties extends SGProperties
	{

		boolean visible;


		public ElementGroupSetProperties()
		{
			super();
		}


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

			if( ( obj instanceof ElementGroupSetProperties ) == false )
			{
				return false;
			}

			ElementGroupSetProperties p = (ElementGroupSetProperties)obj;

			if( p.visible != this.visible ) return false; 

			return true;

		}


		/**
		 * 
		 */
		public String toString()
		{
			String str = new String("[");
			str += new String("visible="+visible+", ");
			str += new String("]");

			return str;
		}
		
	}




}
