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

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


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


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


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


	/**
	 * 
	 */
	protected double mRulerUnit = SGConstants.CM_POINT_RATIO;


	/**
	 * 
	 */
	protected boolean mSelectedFlag = false;


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



	/**
	 * 
	 */
	protected static final String MOVE_GRAPH_TO_FRONT = "Move this graph to front";

	/**
	 * 
	 */
	protected static final String MOVE_GRAPH_TO_BACK = "Move this graph to back";

	/**
	 * 
	 */
	protected static final String REMOVE_GRAPH = "Remove this graph";



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



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

		return list;
	}



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


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


	/**
	 * 
	 */
	protected boolean removeElements( final SGElementGroup group )
	{
		ArrayList groupList = this.mDrawingElementGroupList;

		if( groupList.size() == 1 )
		{
			System.out.println("size of list is equal to 1!");
			return true;
		}

		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( boolean b )
	{
		this.mVisibleFlag = b;
	}


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



	/**
	 * 
	 * @return
	 */
	public boolean shiftColorList()
	{
		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			group.shiftColorList();
		}
		
		return true;
	}


	/**
	 * 
	 */
	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 int w, final int h, final float ratio )
	{

		this.mMagnification = ratio;

		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			group.zoom(w,h,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 )
	{
		for( int ii=0; ii<this.mDrawingElementGroupList.size(); ii++ )
		{
			SGElementGroup group = (SGElementGroup)this.mDrawingElementGroupList.get(ii);
			if( group.isVisible() == false )
			{
				continue;
			}

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

		return false;
	}


	/**
	 * 
	 */
	protected abstract boolean clickDrawingElements( final MouseEvent e );


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


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



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

//System.out.println(wp.ep);

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

		return true;
	}



	/**
	 * 
	 */
	public boolean readProperties( final BufferedReader br, final SGProperties prop )
		throws IOException
	{
		if( br==null || prop==null )
		{
			return false;
		}

		if( ( prop instanceof ElementGroupSetProperties ) == false )
		{
			return false;
		}
			
		ElementGroupSetProperties p = (ElementGroupSetProperties)prop;

		p.visible = this.isVisible();

		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;
		}
		
	}




}
