package dfatool.strategy.graph;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Set;

import patterns.Observer;
import patterns.Subject;
import dfatool.expressions.Expression;
import dfatool.operations.SetOperations;
import dfatool.parser.ExpressionParser;
import dfatool.parser.LanguageUtil;
import dfatool.parser.ParseException;
import dfatool.strategy.elements.Atom;
import dfatool.strategy.elements.Configuration;
import dfatool.strategy.elements.Context;
import dfatool.strategy.elements.Description;
import dfatool.strategy.elements.Network;
import dfatool.strategy.elements.NetworkElement;
import dfatool.values.IntValue;
import dfatool.values.SetValue;
import dfatool.values.Value;

public class CommunicationGraph extends Subject implements Observer{
	
	
	private IGraph graph;
	private static CommunicationGraph instance;
	
	private CommunicationGraph() {
//		Configuration.getInstance().getContext().register(this);
//		Network.createNetwork().register(this);
		generateGraph()
	}
	
	public void reInit(){
		instance = new CommunicationGraph();
	}
	
	
	public static CommunicationGraph getInstance() {
		if(instance == null)
			instance = new CommunicationGraph();
		return instance;
	}
	
	private IGraph generateGraph(){
		System.out.println("Generating graph!");
		graph = new Graph();
		Network net = Configuration.getInstance().getNetwork();
		Description desc = Configuration.getInstance().getDescription();
		Context c = Configuration.getInstance().getContext();
		for(NetworkElement ne : net.getList()){
			System.out.println(ne.toString());
			Atom at = desc.getAtom(ne.getName());
			Set<Value> setOfInts = ((SetValue) LanguageUtil.parseString(ne.getExpression()).evaluate(c));
			for(Value v : setOfInts){
				IntValue i = (IntValue) v;
				Value alphaVal = LanguageUtil.parseAndEvalWithId(at.getAlphabet(), i.getValue());
				System.out.println("Atom :"+at.getName()+i.getValue()+" Alpha = "+alphaVal.toString());
				graph.addNode(new NetworkNode(ne.getName(),i.getValue(),(SetValue) alphaVal));
			}
		}
		generateConnections();
		System.out.println("Graph with connecctions:"+graph.getNodes().size());
		return graph;
	}
	
	public IGraph getGraph() {
		return graph;
	}
	
	private void generateConnections() {
		List<INode> list = graph.getNodes();
		List<INode> stack = graph.getNodes();
		for(INode n1 : list){
			stack.remove(0);
			for(INode n2 : stack){
				if(!n1.getIdentifier().equals(n2.getIdentifier())){
					NetworkNode nn1 = (NetworkNode) n1;
					NetworkNode nn2 = (NetworkNode) n2;
					if(!SetOperations.inter(nn1.getAlphabet(),nn2.getAlphabet()).isEmpty()){
						nn1.getConnections().add(nn2);
						nn2.getConnections().add(nn1);
						nn1.getZestConnections().add(nn2);
					}
				}else{
					System.out.println("Salcifufu!");
				}
			}
		}
	}
	
	public void updateWithoutGeneration() {
		alertAll();
	}
	

	@Override
	public void update() {
		generateGraph();
		alertAll();
	}
}
