package fha.inf3.graph;

import java.util.*;

public class WeightedGraphImpl implements WeightedGraph, Cloneable {

	protected Graph graph;
	private Map weights;

	static class EdgeKey {
		Object from, to;
		EdgeKey(Object from, Object to) {
			this.from = from;
			this.to = to;
		}
		public boolean equals(Object x) {
			return x instanceof EdgeKey
				&& ((EdgeKey) x).from.equals(from)
				&& ((EdgeKey) x).to.equals(to);
		}
		public int hashCode() {
			return from.hashCode() + to.hashCode();
		}
	}

	public WeightedGraphImpl(Graph graph) {
		this.graph = graph;
		weights = new HashMap();
	}

	public final boolean addEdge(Object from, Object to) {
		return false;
	}

	public boolean addEdge(Object from, Object to, double w) {
		boolean res = graph.addEdge(from, to);
		if (res) {
			weights.put(new EdgeKey(from, to), new Double(w));
			if (!isDirected()) {
				weights.put(new EdgeKey(to, from), new Double(w));
			}
		}
		return res;
	}

	public double getEdgeWeight(Object from, Object to) {
		Object x = weights.get(new EdgeKey(from, to));
		if (x != null)
			return ((Double) x).doubleValue();
		else
			return 0;
	}

	public boolean addVertex(Object vertex) {
		return graph.addVertex(vertex);
	}

	public boolean removeEdge(Object from, Object to) {
		weights.remove(new EdgeKey(from, to));
		if (!isDirected())
			weights.remove(new EdgeKey(to, from));
		return graph.removeEdge(from, to);
	}

	public boolean isDirected() {
		return graph.isDirected();
	}

	public int getNofVertices() {
		return graph.getNofVertices();
	}

	public int getNofEdges() {
		return graph.getNofEdges();
	}

	public Set getVertices() {
		return graph.getVertices();
	}

	public Set getAdjacentVertices(Object vertex) {
		return graph.getAdjacentVertices(vertex);
	}

	public Object clone(){
		WeightedGraphImpl g = null;
		try {
			g = (WeightedGraphImpl)super.clone();
		}
		catch(CloneNotSupportedException e){}
		g.graph = (Graph)g.graph.clone();
		g.weights = (Map)((HashMap)g.weights).clone();
		return g;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("weighted ");
		if (isDirected())
			sb.append("di");
		sb.append("graph:\n");

		Iterator it = getVertices().iterator();
		while (it.hasNext()) {
			Object from = it.next();
			sb.append(from + ":\t");

			Iterator eit = getAdjacentVertices(from).iterator();
			if (eit.hasNext()) {
				sb.append(eit.next());
				while (eit.hasNext()) {
					Object to = eit.next();
					sb.append(", " + to);
					sb.append("(" + getEdgeWeight(from, to) + ")");
				}
			}
			sb.append('\n');
		}
		sb.append('\n');
		return sb.toString();
	}

}
