
package emn.fr.ascola.extractor;


import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.TypeDeclaration;

/**
 * Dedicated visitor to extract the communications of a type of interest
 * MethodDeclaration
 * MethodInvocation
 * TODO method static invocation ?
 */
class ExtractCommunications extends SimpleVisitor {

	/**
	 *  Current type binding.
	 */
	private ITypeBinding maintype = null;
	
	private String fullname;
	
	/**
	 * Visit ASTNode.
	 * to collect a possible structure.
	 */
	public void preVisit(ASTNode node) {
		// catch the enclosing type
		if (node.getNodeType() == ASTNode.TYPE_DECLARATION) {
			TypeDeclaration main = (TypeDeclaration) node;
			this.maintype = main.resolveBinding();
			this.fullname = maintype.getBinaryName();
			//System.out.println(" ExtracComm for type " + this.fullname);
		}
	}

	/**
	 * Visit method call to find messages.
	 * inner expressions are catched and also static call
	 * TODO verifier que celles des for et autres cas passent bien ici
	 */
	public boolean visit(MethodInvocation call) {
		//System.out.println(" visit methode invoc " + call);
		IMethodBinding im = call.resolveMethodBinding();
		// receiver expression
		Expression exp = call.getExpression();
		// name for the receiver expression
		String recname;
		if (exp != null) {
			ITypeBinding rec = exp.resolveTypeBinding();
			recname = rec.getBinaryName();
		} else {
			// TODO probleme la sinon ca peut-etre this
			// voir AssertStatement
			if (call.getName().getFullyQualifiedName().equals("assertTrue")) {
				System.err.println(" call exp null ? fait chier !!!! " + call);	
				recname = "PROBLEM!!!!";
			} else {
				// assume it is this.call
				recname = this.fullname;
			}
		}
		// catch only communications between types of interests
		if (ASTActionDelegate.table.isOfInterest(recname) 
				&& ASTActionDelegate.table.isOfInterest(this.fullname)) {
			//System.out.println("visit comm from " + this.fullname + " to " + recname);
			ASTActionDelegate.communications.addCom(this.fullname, recname, im);
		}
		// needed to parse internal calls
		return true;
	}
	
	//-------------- for testing detection des appel static final
	// mais pas simple ca 
	public boolean visit(FieldAccess fa) {
		//System.out.println("FieldAccess " + fa.getName());
		return true;
	}
	
	/**
	 * Acces to static final TODO.
	 * on ne devrait pas compter dans la classe
	 * capture  aussi la declaration
	 */
	public boolean visit(QualifiedName qa) {
		//System.out.println("QualifiedName " + qa.getQualifier() + "  . " + qa.getName());
		return true;
	}

}