/*
 * Created on 2004/06/15
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package jp.riken.brain.ni.samuraigraph.figure.java2d;

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


/**
 * @author kuromaru
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public abstract class SGSignificantDifferenceSymbol2D extends SGSignificantDifferenceSymbol
	implements SGIDrawingElementJava2D
{


	/**
	 * 
	 */
	protected SGDrawingElementString2DExtended mStringElement = new SGDrawingElementString2DExtended("*");


	/**
	 * 
	 */
	protected SGDrawingElementLine2D mHorizontalLine = new SGDrawingElementLine2D();


	/**
	 * 
	 */
	protected SGDrawingElementLine2D mPerpendicularLine1 = new SGDrawingElementLine2D();


	/**
	 * 
	 */
	protected SGDrawingElementLine2D mPerpendicularLine2 = new SGDrawingElementLine2D();


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


	/**
	 * 
	 */
	public SGSignificantDifferenceSymbol2D(
		final float x,
		final float y,
		final float w,
		final float hl,
		final float hr )
	{
		super(x,y,w,hl,hr);
	}



	/**
	 * 
	 */
	protected boolean createDrawingElement()
	{
//System.out.println("<< createDrawingElement >>");

		final SGTuple2f leftTop = new SGTuple2f(
			this.getX(),
			this.getY() );

		final SGTuple2f rightTop = new SGTuple2f(
			this.getX() + this.getWidth(),
			this.getY() );

		final SGTuple2f leftBottom = new SGTuple2f(
			this.getX(),
			this.getY() + this.getPerpendicularHeight1() );

		final SGTuple2f rightBottom = new SGTuple2f(
			this.getX() + this.getWidth(),
			this.getY() + this.getPerpendicularHeight2() );

//System.out.println(this.getX()+"  "+this.getY());

		this.mHorizontalLine.setTermPoints( leftTop, rightTop );
		this.mPerpendicularLine1.setTermPoints( leftTop, leftBottom );
		this.mPerpendicularLine2.setTermPoints( rightTop, rightBottom );

		final Rectangle2D rect = this.mStringElement.getElementBounds();
		final float rectWidth = (float)rect.getWidth();
		final float rectHeight = (float)rect.getHeight();


		final float strX = this.getX() + this.getWidth()/2.0f - (rectWidth/2.0f);
		float strY;
		if( !this.isFlippingVertical() )
		{
			strY = this.getY() - this.getSpace() - rectHeight;
		}
		else
		{
			strY = this.getY() + this.getSpace();
		}

		this.mStringElement.setLocation( strX, strY );


		return true;

	}



	/**
	 * 
	 */
	public ArrayList getDrawingElementList()
	{
		ArrayList list = new ArrayList();
		list.add(this.mHorizontalLine);
		list.add(this.mPerpendicularLine1);
		list.add(this.mPerpendicularLine2);
		return list;
	}



	/**
	 * 
	 * @return
	 */
	public boolean isFlippingHorizontal()
	{
		return ( this.mWidth < 0.0f );
	}


	/**
	 * 
	 * @return
	 */
	public boolean isFlippingVertical()
	{
		return ( this.isFlippingVertical1() && this.isFlippingVertical2() );
	}



	/**
	 * 
	 * @return
	 */
	protected boolean isFlippingVertical1()
	{
		return ( this.mPerpendicularHeight1 < 0.0f );
	}


	/**
	 * 
	 * @return
	 */
	protected boolean isFlippingVertical2()
	{
		return ( this.mPerpendicularHeight2 < 0.0f );
	}


	/**
	 * 
	 * @return
	 */
	public boolean isFlippingVerticalLeft()
	{
		return ( !this.isFlippingHorizontal() ? this.isFlippingVertical1() : this.isFlippingVertical2() );
	}


	/**
	 * 
	 * @return
	 */
	public boolean isFlippingVerticalRight()
	{
		return ( !this.isFlippingHorizontal() ? this.isFlippingVertical2() : this.isFlippingVertical1() );
	}



	/**
	 * 
	 * @return
	 */
	public float getLeftHeight()
	{
		if( !this.isFlippingHorizontal() )
		{
			return this.getPerpendicularHeight1();
		}
		else
		{
			return this.getPerpendicularHeight2();
		}
	}


	/**
	 * 
	 * @return
	 */
	public float getRightHeight()
	{
		if( !this.isFlippingHorizontal() )
		{
			return this.getPerpendicularHeight2();
		}
		else
		{
			return this.getPerpendicularHeight1();
		}
	}



	/**
	 * 
	 * @param h
	 * @return
	 */
	public boolean setLeftHeight( final float h )
	{
		if( !this.isFlippingHorizontal() )
		{
			this.setPerpendicularHeight1( h );
		}
		else
		{
			this.setPerpendicularHeight2( h );
		}
		return true;
	}



	/**
	 * 
	 * @param h
	 * @return
	 */
	public boolean setRightHeight( final float h )
	{
		if( !this.isFlippingHorizontal() )
		{
			this.setPerpendicularHeight2( h );
		}
		else
		{
			this.setPerpendicularHeight1( h );
		}
		return true;
	}



	/**
	 * 
	 */
	protected Point2D getHorizontalTerm1()
	{
		Point2D pos = new Point2D.Float(
			this.getX(), this.getY()
		);
		return pos;
	}



	/**
	 * 
	 */
	protected Point2D getHorizontalTerm2()
	{
		Point2D pos = new Point2D.Float(
			this.getX() + this.getWidth(), this.getY()
		);
		return pos;
	}


	/**
	 * 
	 */
	public Point2D getLeftJoint()
	{
		final Point2D pos;
		if( !this.isFlippingHorizontal() )
		{
			pos = this.getHorizontalTerm1();
		}
		else
		{
			pos = this.getHorizontalTerm2();
		}
		return pos;
	}


	/**
	 * 
	 */
	public Point2D getLeftTerm()
	{
		final Point2D pos = this.getLeftJoint();
		pos.setLocation(
			pos.getX(),
			pos.getY() + this.getLeftHeight()
		);
		return pos;
	}



	/**
	 * 
	 */
	public Point2D getRightJoint()
	{
		final Point2D pos;
		if( !this.isFlippingHorizontal() )
		{
			pos = this.getHorizontalTerm2();
		}
		else
		{
			pos = this.getHorizontalTerm1();
		}
		return pos;
	}



	/**
	 * 
	 */
	public Point2D getRightTerm()
	{
		final Point2D pos = this.getRightJoint();
		pos.setLocation(
			pos.getX(),
			pos.getY() + this.getRightHeight()
		);
		return pos;
	}



	/**
	 * 
	 * @return
	 */
	public Point2D getHorizontalMiddle()
	{
		final Point2D pos = new Point2D.Float(
			this.getX() + this.getWidth()/2.0f,
			this.getY()
		);
		return pos;
	}



	/**
	 * 
	 * @return
	 */
	public Point2D getLeftMiddle()
	{
		final Point2D pos = new Point2D.Float();
		final Point2D joint = this.getLeftJoint();
		final Point2D term = this.getLeftTerm();
		pos.setLocation(
			( joint.getX() + term.getX() )/2.0,
			( joint.getY() + term.getY() )/2.0
		);
		return pos;
	}



	/**
	 * 
	 * @return
	 */
	public Point2D getRightMiddle()
	{
		final Point2D pos = new Point2D.Float();
		final Point2D joint = this.getRightJoint();
		final Point2D term = this.getRightTerm();
		pos.setLocation(
			( joint.getX() + term.getX() )/2.0,
			( joint.getY() + term.getY() )/2.0
		);
		return pos;
	}




	/**
	 * 
	 */
	public SGDrawingElementString getStringElement()
	{
		return this.mStringElement;
	}


	/**
	 * 
	 */
	public boolean setMagnification( final float mag )
	{
		super.setMagnification(mag);

		ArrayList dList = this.getDrawingElementList();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			SGDrawingElement el = (SGDrawingElement)dList.get(ii);
			el.setMagnification(mag);
		}

		this.mStringElement.setMagnification(mag);

		return true;
	}


	/**
	 * 
	 */
	public boolean setLineWidth( final float width )
	{
		super.setLineWidth( width );

		ArrayList dList = this.getDrawingElementList();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			SGDrawingElementLine el = (SGDrawingElementLine)dList.get(ii);
			el.setLineWidth(width);
		}

		return true;
	}


	/**
	 * 
	 */
	public boolean contains( final int x, final int y )
	{
		ArrayList dList = this.getDrawingElementList();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			SGDrawingElement el = (SGDrawingElement)dList.get(ii);
//System.out.println(el);
//System.out.println(x+"  "+y);
			if( el.contains(x,y) )
			{
				return true;
			}
		}

		return false;
	}


	/**
	 * 
	 */
	public ArrayList getShapeList()
	{
		ArrayList dList = this.getDrawingElementList();
		ArrayList list = new ArrayList();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			SGDrawingElementLine2D el = (SGDrawingElementLine2D)dList.get(ii);
			list.add( el.getShape() );
		}

		return list;
	}



	/**
	 * 
	 */
	public Shape getConnectedShape()
	{
		GeneralPath gp = new GeneralPath();
		gp.append( this.mPerpendicularLine1.getShape(), true );
		gp.append( this.mHorizontalLine.getShape(), true );
		gp.append( this.mPerpendicularLine2.getShape(), true );

		return gp;
	}



	/**
	 * 
	 */
	public boolean zoom( final float mag )
	{
		super.zoom( mag );
		this.createDrawingElement();
		return true;
	}



	/**
	 * 
	 * @return
	 */
	public Rectangle2D getElementBounds()
	{
		ArrayList rectList = new ArrayList();
		rectList.add( this.getLineBounds() );
		rectList.add( this.getStringBounds() );
		Rectangle2D rect = SGUtility.createUnion(rectList);

		return rect;
	}


	/**
	 * 
	 */
	public Rectangle2D getLineBounds()
	{
		ArrayList rectList = new ArrayList();
		ArrayList dList = this.getDrawingElementList();
		for( int ii=0; ii<dList.size(); ii++ )
		{
			SGDrawingElementLine2D el = (SGDrawingElementLine2D)dList.get(ii);
			rectList.add( el.getShape().getBounds2D() );
		}

		Rectangle2D rect = SGUtility.createUnion(rectList);

		return rect;
	}


	/**
	 * 
	 */
	public Rectangle2D getStringBounds()
	{
		return this.mStringElement.getElementBounds();
	}



	/**
	 * 
	 * @param g2d
	 */
	public void drawSymbol( final Graphics2D g2d )
	{

		final float lineWidth = this.mMagnification*this.getLineWidth();
		g2d.setStroke(
			new BasicStroke
			(
				lineWidth,
				BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_MITER
			)
		);
		
		g2d.setPaint( this.getColor() );

		Shape sh = this.getConnectedShape();
		g2d.draw(sh);


		// string
		SGDrawingElementString2DExtended sElement
			= (SGDrawingElementString2DExtended)this.getStringElement();
		sElement.drawString(g2d);
		
	}


}
