import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.font.*;
/**
 * ConnectionBox is a ViewObject which represents a connection
 */
class ConnectionBox extends ViewObject {
	/**
	 * The connection
	 * */
	Connection conn;
	/**
	 * Returns the connection
	 * @return conn the connection represented
	 * */
	public Connection getConnection() {
		return conn;
	}
	/**
	 * X Coord
	 * */
	int X=0;
	/**
	 * Y Coord
	 * */
	int Y=0;
	/**
	 * Width of box
	 * */
	int width=25;
	/**
	 * Height of box
	 * */
	int height=25;
	/**
	 * Node/Knob Width
	 * */
	int knobwidth = 10;
	/**
	 * Node/Knob Height
	 * */
	int knobheight = 10;
	/**
	 * Does it have an inputKnob?
	 * */
	boolean inputKnob = true;
	/**
	 * Does it have an outputKnob?
	 * */
	boolean outputKnob = false;
	/**
	 * Used to display the font
	 * */
	GlyphVector nameVec = null;
	/**
	 * The current font to use.
	 * */
	Font gFont = new JLabel().getFont();
	/**
	 * Default Constructor
	 * */
	public ConnectionBox() {
		conn = new Connection();
		conn.setName("UnNamed");
		init();
	}
	/**
	 * Constructor sets the name of the connection
	 * */
	public ConnectionBox(String name) {
		conn = new Connection();
		conn.setName(name);
		init();
	}
	/**
	 * Create and set the connection
	 * */
	public ConnectionBox(Connection conn) {
		this.conn = conn;
		init();
	}
	/**
	 * Initialize the object and set the knob visibility
	 * */
	void init() {
		inputKnob = (!(conn.getType() == Connection.INPUT));
		outputKnob = (!(conn.getType() == Connection.OUTPUT));
	}
	/**
	 * Paints the object on a graphical surface.
	 * */
	public void paintOn(Graphics g) {
		Graphics2D g2d = (Graphics2D)g;
		if (g2d == null) { return; }
		//if (gFont == null) { throw new Error("GFONT NULL!"); }
		if (nameVec == null) {
			nameVec =
			gFont.createGlyphVector(g2d.getFontRenderContext(),conn.getName());
		}
		Rectangle rect =
		nameVec.getPixelBounds(g2d.getFontRenderContext(),(float)(X+knobwidth),(float)Y);
		rect.x=rect.x-4;
		rect.y=rect.y-4;
		rect.width=rect.width+4;
		rect.height=rect.height+4;
		g2d.setColor(new Color(255,0,0));
		g2d.drawGlyphVector(nameVec,(float)(X+knobwidth),(float)(Y)+rect.height);
		rect.y+=rect.height;
		g2d.setColor(new Color(255,0,255));
		g2d.draw(rect);
		g2d.setColor(new Color(0,0,255));
		if (inputKnob) {
			g2d.fillOval(X,Y,knobwidth,knobheight); //input
		}
		if (outputKnob) {
			g2d.fillOval((int)(rect.getX()+rect.getWidth()),Y,knobwidth,knobheight);
		}
		//ouput
		width =(int)( rect.getWidth() + 2*knobwidth);
		height = (int)Math.max(knobheight,rect.getHeight());

	}
	/**
	 * At point x,y on the plane was this object clicked on?
	 * @param x the x coord
	 * @param y the y coord
	 * @return true if object was clicked, false otherwise
	 * */
	public boolean wasClicked(int x,int y) {
		if (x >= X && x <= (X+width)) {
			if (y >=Y && y <= (Y+height)) {
				return true;
			}
		}
		return false;
	}
	/**
	 * At point x,y on the plane was this object's textbox was clicked on?
	 * @param x the x coord
	 * @param y the y coord
	 * @return true if object was clicked, false otherwise
	 * */
	public boolean hasClickedText(int x,int y) {
		if (x >= X+knobwidth  && x <= (X+width-knobwidth)) {
			if (y>=Y && y <= (Y+height)) {
				return true;
			}
		}
		return false;
	}
	/**
	 * At point x,y on the plane was one of this object's knobs were
	 * clicked on?
	 * @param x the x coord
	 * @param y the y coord
	 * @return true if object was clicked, false otherwise
	 * */
	public boolean hasClickedKnob(int x,int y) {
		return (wasClicked(x,y) && !hasClickedText(x,y));
	}
	/**
	 * At point x,y on the plane was one of this object's input knob was
	 * clicked on?
	 * @param x the x coord
	 * @param y the y coord
	 * @return true if object was clicked, false otherwise
	 * */
	public boolean hasClickedInputKnob(int x,int y) {
		if ( x >= X  && x <= (X+knobwidth)) {
			if (y>=Y && y <= (Y+height)) {
				return true;
			}
		}
		return false;	
	}
	/**
	 * At point x,y on the plane was one of this object's input knob was
	 * clicked on?
	 * @param x the x coord
	 * @param y the y coord
	 * @return true if object was clicked, false otherwise
	 * */
	public boolean hasClickedOutputKnob(int x,int y) {
		if ( x >= X+width-knobwidth && x <= (X+width)) {
			if (y>=Y && y <= (Y+height)) {
				return true;
			}
		}
		return false;	
	}	
	/**
	 * Is the object draggable?
	 * */
	public boolean draggable() {
		return true;
	}
	/**
	 * Drag or move object to x,y
	 * @param x the new xcoord
	 * @param y the new ycoord
	 * */
	public void dragTo(int x,int y) {
		X = x;
		Y = y;
	}
	/**
	 * Returns the location of the center of the InputKnob
	 * */
	public Point getInputKnobLocation() {
		return new Point(X+knobwidth/2,Y+knobheight/2);
	}
	/**
	 * Returns the location of the center of the OutputKnob
	 * */
	public Point getOutputKnobLocation() {
		return new Point(X+width-knobwidth/2,Y+knobheight/2);
	}
	/**
	 * hashcode based on name and ID
	 * */
	public int hashCode() {
		String h = conn.getName()+conn.getID();
		return h.hashCode();
	}
	/**
	 * get the Maximum X coordinate 
	 * */
	int getMaxX() {
		return X+width+2*knobwidth;
	}
	/**
	 * get the Maximum Y coordinate 
	 * */
	int getMaxY() {
		return Y+height+2*knobheight;
	}
	/**
	 * Is there an input knob?
	 * */
	boolean hasInputKnob() {
		return inputKnob;
	}
	/**
	 * Is there an output knob?
	 * */
	boolean hasOutputKnob() {
		return outputKnob;
	}
}
