import java.util.LinkedList;
import java.util.List;

/**
 * The vertex class represents a single vertex of a random graph.
 * It keeps track of adjacent vertices and edges attached to this vertex
 * as well as the connected component it resides in.
 */
public class Vertex {
	private Component comp;
	private int id;
	private List<Vertex> localVerts;
	private List<Edge> localEdges;

	// Create a new vertex and new component.
	public Vertex() {
		comp = new Component(this);
		localVerts = new LinkedList<Vertex>();
	}

	// Create a new vertex with a specific id.
	public Vertex(int index) {
		id = index;
		localVerts = new LinkedList<Vertex>();
		localEdges = new LinkedList<Edge>();
	}

	// Change the link to the component this vertex resides in.
	public void changeComponent(Component c) {
		comp = c;
	}

	// Returns the component this vertex resides in.
	public Component getComponent() {
		return comp;
	}

	// Returns this vertex's id.
	public int getId() {
		return id;
	}

	// Returns a list of all adjacent vertices.
	public List<Vertex> getLocalVertices() {
		return localVerts;
	}

	// Add an edge to this vertex.
	public void addEdge(Edge e) {
		localEdges.add(e);
	}

	// Add an edge between this vertex and another unless one already exists or the other
	// vertex is this one.
	public boolean addEdge(Vertex v2) {
		if (v2.equals(this) || localVerts.contains(v2)) {
			return false;
		}
		Edge e = new Edge(this, v2);
		localVerts.add(v2);
		v2.addVertex(this);
		comp.addEdge(e);
		if (!this.comp.equals(v2.comp)) {
			comp.mergeComponents(v2.comp);
		}
		return true;
	}

	// Add an edge between this vertex and another, even is an edge is already present
	// or the other vertex is this one. This allows for multigraphs.
	public boolean addMultigraphEdge(Vertex v2) {
		Edge e = new Edge(this, v2);
		if (!localVerts.contains(v2)) {
			localVerts.add(v2);
			if (!this.equals(v2)) {
				v2.addVertex(this);
			}
		}
		comp.addEdge(e);
		if (!this.comp.equals(v2.comp)) {
			comp.mergeComponents(v2.comp);
		}
		return true;
	}

	// Add a vertex to the adjacency list.
	public void addVertex(Vertex v2) {
		localVerts.add(v2);
	}
}
