package aspectEditor.aspectEditorUtils;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;

import edu.neu.ccs.demeter.aplib.TraversalGraph.EdgeSet;
import edu.neu.ccs.demeter.aplib.TraversalGraph.NodeSet;
import edu.neu.ccs.demeter.aplib.cd.ClassGraph;
class BCompound extends NodeSubsetExpression {
	
	public void interpretExpression(SelectorL s, ClassGraph c) {
		Enumeration e = this.get_args().elements();
		String operation = this.get_op().getClass().getName().toString();
		NodeSubsetExpression nse1=null;
		NodeSubsetExpression nse2=null;
		
		//counter to tell which argument you're on
		int i=0;
		
		//get the two arguments in the BinaryCompound as nse1 and nse2
		while(e.hasMoreElements()){
			Object o = e.nextElement();
			if(i==0){
				nse1=(NodeSubsetExpression)o;
				
			}
			if(i==1){
				nse2=(NodeSubsetExpression)o;
			}
			i++;
		}
		
		//if it's Union, just perform interpret expression on both args
		//that will automatically highlight for both args
		if(operation.equals("aspectEditor.aspectEditorUtils.Union")){
			nse1.interpretExpression(s,c);
			nse2.interpretExpression(s,c);
		}
		
		if(operation.equals("aspectEditor.aspectEditorUtils.Intersection")){
			
			//get nodes traversed from the first argument
			nse1.interpretExpression(s,c);
			HashSet nse1Nodes = Main.nodesTraversed;
			HashSet nse1Edges = Main.edgesTraversed;
			
			//wipe out these HashSets in Main, because they were just affected by interpret Expression
			Main.nodesTraversed=new HashSet();
			Main.edgesTraversed=new HashSet();
			
			//get nodes traversed from the second argument
			nse2.interpretExpression(s,c);
			HashSet nse2Nodes = Main.nodesTraversed;
			HashSet nse2Edges = Main.edgesTraversed;
			
			//System.out.println("nse1Nodes:"+nse1Nodes.size()+" nse2Nodes:"+nse2Nodes.size());
			
			//wipe out these HashSets in Main, because they were just affected by interpret Expression
			Main.nodesTraversed=new HashSet();
			Main.edgesTraversed=new HashSet();
			
			
			////////collect all the node names in nse2///////////////
			HashSet nodeNamesInnse2 = new HashSet();
			Iterator i5 = nse2Nodes.iterator();
			
			while(i5.hasNext()){
				NodeSet currNode = (NodeSet)i5.next(); 
				//System.out.println(currNode.getNode().toString());
				nodeNamesInnse2.add(currNode.getNode().toString());
			}
			
			//collect all the edge set names in nse2///////////
			HashSet edgeNamesInnse2 = new HashSet();
			Iterator i6 = nse2Edges.iterator();
			
			while(i6.hasNext()){
				EdgeSet currNode = (EdgeSet)i6.next(); 
				//System.out.println(currNode.getEdge().toString());
				edgeNamesInnse2.add(currNode.getEdge().toString());
			}
			
			//Below we're going to find all node sets and edges that arg1 and arg2 have in common
			//we compare node and edge names
			
			//make new HashSet for all nodes we would like to highlight
			HashSet nodesToHighlight = new HashSet();
			Iterator i2 = nse1Nodes.iterator();
			
			//find all nodes traversed in both BinaryOp args
			while(i2.hasNext()){
				NodeSet currNode = (NodeSet)i2.next();
				if(nodeNamesInnse2.contains(currNode.getNode().toString())){
					nodesToHighlight.add(currNode);
				}
			}
			
			//make new HashSet for all edges we would like to highlight
			HashSet edgesToHighlight = new HashSet();
			Iterator i3 = nse1Edges.iterator();
			
			//find all edges traversed in both BinaryOp args
			//we compare edge names
			while(i3.hasNext()){
				
				EdgeSet currEdge = (EdgeSet)i3.next();
				if(edgeNamesInnse2.contains(currEdge.getEdge().toString())){
					edgesToHighlight.add(currEdge);
				}
			}
			
			//now add the nodes and edges to highlight back to Main's variables
			Main.nodesTraversed.addAll(nodesToHighlight);
			Main.edgesTraversed.addAll(edgesToHighlight);
		}
	}
	
	protected BinaryOp op;
	public BinaryOp get_op() { return op; }
	public void set_op(BinaryOp new_op) { op = new_op; }
	protected NodeSubsetExpression_PCList args;
	public NodeSubsetExpression_PCList get_args() { return args; }
	public void set_args(NodeSubsetExpression_PCList new_args) { args = new_args; }
	public BCompound() { super(); }
	public BCompound(BinaryOp op, NodeSubsetExpression_PCList args) {
		super();
		set_op(op);
		set_args(args);
	}
	public static BCompound parse(java.io.Reader in) throws ParseException { return new Parser(in)._BCompound(); }
	public static BCompound parse(java.io.InputStream in) throws ParseException { return new Parser(in)._BCompound(); }
	public static BCompound parse(String s) {
		try { return parse(new java.io.StringReader(s)); }
		catch (ParseException e) {
			throw new RuntimeException(e.toString());
		}
	}
	void universal_trv0_bef(UniversalVisitor _v_) {
		super.universal_trv0_bef(_v_);
		((UniversalVisitor) _v_).before(this);
	}
	
	void universal_trv0_aft(UniversalVisitor _v_) {
		((UniversalVisitor) _v_).after(this);
		super.universal_trv0_aft(_v_);
	}
	
	void universal_trv0(UniversalVisitor _v_) {
		universal_trv0_bef(_v_);
		((UniversalVisitor) _v_).before_op(this, op);
		op.universal_trv0(_v_);
		((UniversalVisitor) _v_).after_op(this, op);
		((UniversalVisitor) _v_).before_args(this, args);
		args.universal_trv0(_v_);
		((UniversalVisitor) _v_).after_args(this, args);
		super.universal_trv0(_v_);
		universal_trv0_aft(_v_);
	}
	
	
}
