package dfatool.strategy.graph;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import dfatool.parser.ParseException;
import dfatool.strategy.graph.TarjanAlgorithm.Bridge;
import dfatool.strategy.verification.elements.EssentialComponent;
import dfatool.strategy.verification.elements.EssentialComponents;
import dfatool.util.Pair;

public class Graph implements IGraph{
	
	private Map<String,Map<Integer,INode>> map;
	
	private static Graph instance;
	
	public Graph(){
		map = new HashMap<String, Map<Integer,INode>>();
	}
	
	@Override
	public void addNode(INode node) {
		NodeIdentifier identifier = node.getIdentifier();
		String atomName = identifier.getFst();
		int id = identifier.getSnd();
		if(!map.containsKey(atomName))
			map.put(atomName, new HashMap<Integer,INode>());
		map.get(atomName).put(id, node);
	}
	
	public boolean hasNode(INode node){
		NodeIdentifier identifier = node.getIdentifier();
		String atomName = identifier.getFst();
		int id = identifier.getSnd();
		return map.containsKey(atomName) && map.get(atomName).containsKey(id); 
	}

	@Override
	public void removeNode(INode node) {
		NodeIdentifier identifier = node.getIdentifier();
		String atomName = identifier.getFst();
		int id = identifier.getSnd();
		if(!map.containsKey(atomName))
			return;
		map.get(atomName).remove(id);
	}

	@Override
	public INode getNodeByIdentifier(NodeIdentifier identifier) {
		String atomName = identifier.getFst();
		int id = identifier.getSnd();
		if(!map.containsKey(atomName))
			return null;
		return map.get(atomName).get(id);
	}

	@Override
	public List<INode> getNodes() {
		List<INode> ret = new LinkedList<INode>();
		for(String atomName : map.keySet())
			ret.addAll(map.get(atomName).values());
		return ret;
	}
	
	public void removeEdges(List<Bridge> bridges){
		for(Bridge b: bridges){
			NetworkNode nn1 = (dfatool.strategy.graph.NetworkNode) getNodeByIdentifier(b.getFst());
			NetworkNode nn2 = (dfatool.strategy.graph.NetworkNode) getNodeByIdentifier(b.getSnd());
			nn1.getConnections().remove(nn2);
			nn2.getConnections().remove(nn1);
			nn1.getZestConnections().remove(nn2);
			nn2.getZestConnections().remove(nn1);
		}
	}
	
	public List<EssentialComponent> getConnectedComponents(){
		List<EssentialComponent> essentialComponents = new ArrayList<EssentialComponent>();
		HashSet<INode> visited = new HashSet<INode>();
		int i = 0;
		for(INode node : getNodes()){
			if(!visited.contains(node)){
				visited.add(node);
				essentialComponents.add(getConnectedComponent(null, node,visited));
				i++;
			}
		}
		return essentialComponents;
	}
	
	
	
	private EssentialComponent getConnectedComponent(String name, INode node,
			HashSet<INode> visited) {
		EssentialComponent ec = new EssentialComponent(name);
		ec.addComponent(node.getIdentifier());
		addComponents(node, ec, visited);
		return ec;
	}

	private void addComponents(INode node,
			EssentialComponent essentialComponent, HashSet<INode> visited) {
		for(INode n : node.getConnections()){
			if(!visited.contains(n)){
				visited.add(n);
				essentialComponent.addComponent(n.getIdentifier());
				addComponents(n, essentialComponent, visited);
			}
		}
	}
	
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>(10000);
		System.out.println(list.size());
		list.add(1000, "Nana");
		System.out.println(list.get(3));
		System.out.println(list.get(1000));
	}

}
