/* File: Edge.java
 * Author: Jason Gookins
 * Description: This class creates an Edge which connects Nodes in the network.
 */

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.lang.Math;

public class Edge
{
	/************************
	 ** Instance Variables **
	 ************************/

	private Node childNode;
	private Node parentNode;



	/**********************
	 ** Main Constructor **
	 **********************/

	public Edge(Node childNode, Node parentNode)
	{
		this.childNode = childNode;
		this.parentNode = parentNode;
	}



	/***************
	 ** Accessors **
	 ***************/

	public Node getChildNode()
	{
		return this.childNode;
	}

	public Node getParentNode()
	{
		return this.parentNode;
	}



	/**************
	 ** Mutators **
	 **************/

	public void setChildNode(Node newChildNode)
	{
		this.childNode = newChildNode;
	}

	public void setParentNode(Node newParentNode)
	{
		this.parentNode = newParentNode;
	}



	/**************************
	 ** Edge Painting Method **
	 **************************/

	public void paintComponent(Graphics g)
	{
		Graphics2D g2 = (Graphics2D)g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		int childX, childY, parentX, parentY;
		int x1, x2, x3, y1, y2, y3;
		double dirX, dirY, distance;
		double headX, headY, bottomX, bottomY;

		childX = childNode.center().x;
		childY = childNode.center().y;
		parentX = parentNode.center().x;
		parentY = parentNode.center().y;

		dirX = (double)(parentX - childX);
		dirY = (double)(parentY - childY);

		distance = Math.sqrt((dirX * dirX) + (dirY * dirY));

		dirX /= distance;
		dirY /= distance;

		headX = parentX - (25.0 + 6.0) * dirX;
		headY = parentY - (25.0 + 6.0) * dirY;

		bottomX = childX + 25 * dirX;
		bottomY = childY + 25 * dirY;

		x1 = (int)(headX - 3.0 * dirX + 6.0 * dirY);
		x2 = (int)(headX - 3.0 * dirX - 6.0 * dirY);
		x3 = (int)(headX + 6.0 * dirX);

		y1 = (int)(headY - 3.0 * dirY - 6.0 * dirX);
		y2 = (int)(headY - 3.0 * dirY + 6.0 * dirX);
		y3 = (int)(headY + 6.0 * dirY);

		int arcHeadX[] = {x1, x2, x3, x1};
		int arcHeadY[] = {y1, y2, y3, y1};

		g2.setPaint(Color.black);
		g2.draw(new Line2D.Double(childX, childY, parentX, parentY));
		g2.fillPolygon(arcHeadX, arcHeadY, 4);
	}



	/**********************
	 ** Instance Methods **
	 **********************/

	public double containsPoint(int x3, int y3)
	{
		double containsPoint = 0.0;
		int x1, y1, x2, y2;
		double area, squareBase, squareHeight, squareHypotenuse;

		x1 = childNode.center().x;
		y1 = childNode.center().y;
		x2 = parentNode.center().x;
		y2 = parentNode.center().y;

		area = 0.5 * (double)(x1 * y2 + y1 * x3 + x2 * y3 - x3 * y2 - y3 * x1 - x2 * y1);
		squareBase = (double)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
		squareHeight = 4.0 * (area * area)/squareBase;
		squareHypotenuse = squareBase + squareHeight;

		if (squareHypotenuse < ((double)((x3-x1)*(x3-x1) + (y3-y1)*(y3-y1))))
		{
			containsPoint = -1.0;
		}
		else if (squareHypotenuse < ((double)((x3-x2)*(x3-x2) + (y3-y2)*(y3-y2))))
		{
			containsPoint = -1.0;
		}
		else
		{
			containsPoint = squareHeight;
		}

		return containsPoint;
	}

	public void reverse()
	{
		Node tempNode = getChildNode();
		setChildNode(getParentNode());
		setParentNode(tempNode);
	}
}