package dfatool.strategy.verification.elements;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import dfatool.expressions.SetExpression;
import dfatool.operations.SetOperations;
import dfatool.parser.LanguageUtil;
import dfatool.strategy.elements.Atom;
import dfatool.strategy.elements.Configuration;
import dfatool.strategy.elements.Context;
import dfatool.strategy.elements.Description;
import dfatool.strategy.graph.NodeIdentifier;
import dfatool.values.IntValue;
import dfatool.values.SetValue;
import dfatool.values.StringValue;
import dfatool.values.Value;

public class EssentialComponent {
	
	Map<String,Set<Integer>> components;
	String name;
	
	public EssentialComponent(String name) {
		this.name = name;
		components = new HashMap<String,Set<Integer>>();
	}
	
	public void addComponent(NodeIdentifier id){
		Set<Integer> numbers = components.get(id.getFst());
		if(numbers == null){
			numbers = new HashSet<Integer>();
			components.put(id.getFst(),numbers);
		}
		numbers.add(id.getSnd());
	}
	
	public Collection<String> getNames(){
		return components.keySet();
	}
	
	public List<NodeIdentifier> getComponentsList(){
		List<NodeIdentifier> comps = new ArrayList<NodeIdentifier>();
		for(String s : components.keySet())
			for(Integer i : components.get(s))
				comps.add(new NodeIdentifier(s, i));
		return comps;
	}
	
	public Set<NodeIdentifier> getComponentsSet(){
		Set<NodeIdentifier> comps = new HashSet<NodeIdentifier>();
		for(String s : components.keySet())
			for(Integer i : components.get(s))
				comps.add(new NodeIdentifier(s, i));
		return comps;
	}
	
	public Set<Value> getVocabulary(){
		Description d = Configuration.getInstance().getDescription();
		//d.update();
		Set<Value> setOfChannelNames = new HashSet<Value>();
		for(String atomName : components.keySet()){
			for(Integer number : components.get(atomName)){
				Atom at = d.getAtom(atomName);
				Set<Value> alpha = (Set<Value>) LanguageUtil.parseAndEvalWithId(at.getAlphabet(), number);
				for(String otherName : components.keySet()){
					for(Integer otherNumber : components.get(otherName)){
						if(!(otherName.equals(atomName) && number.equals(otherNumber))){
							Atom other = d.getAtom(otherName);
							Set<Value> otherAlpha = (Set<Value>) LanguageUtil.parseAndEvalWithId(other.getAlphabet(), otherNumber);
							setOfChannelNames.addAll(SetOperations.inter(alpha,otherAlpha));
						}
					}
				}
			}
		}
		return setOfChannelNames;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String toConcreteSyntax() {
		String s = "{ ";
		for(String name : components.keySet())
			for(Integer number : components.get(name))
				s += name+"."+number+ ",";
		return s.substring(0,s.length()-1)+" }";
			
	}
	
	public String toString(){
		return getName();
	}
	

}
