package emn.fr.ascola.extractor;

import java.util.Vector;

import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import emn.fr.ascola.view.BasicCommunicationViewer;
import emn.fr.ascola.view.CheckedDialog;
import emn.fr.ascola.view.PrefuseViewer;

/**
 * Launch the basic view after analysis.
 * @author jroyer
 * 5/6/2009
 */
public class LaunchBasic extends ASTActionDelegate {
	
	protected PrefuseViewer view;
	
	protected CheckedDialog cd;
	
	public void run(IAction action) {
		this.init(action);
		// view creation
		this.view = new BasicCommunicationViewer(this.repo_name);
		this.fillView();
	}
	
	/**
	 * Init the process.
	 * @param action
	 */
	protected void init (IAction action) {
		// should checked that analysis was done
		if (this.typesOfInterest.isEmpty()) {
			super.run(action);
		} else {
			// to input repository name
			boolean rep = MessageDialog.openQuestion(this.shell, "New extraction (else current visualisation)", "choose yes for a new extraction");
			if (rep) {
				super.run(action);
			}
		}
		// choice edges kinds
		this.cd = new CheckedDialog(new Shell(Display.getCurrent()));
		this.cd.open();
	}

	// -----------------------------------------------------------------
	/**
	 * Fill the prefuse view with information.
	 */
	public void fillView() {
		// create node first (to simplify the process)
		this.addNodes(this.view);
		//-------- composite edges creation
		if (this.cd.isComposition()) {
			this.addComposites(this.view);
		}
		// -----------put edges for communication: only one edge
		if (this.cd.isCommunication()) {
			this.addCommunications(this.view);
		}
		// -----------------------
		// add direct subtyping links
		if (this.cd.isSubtyping()) {
			this.addSubtyping(this.view);
		}
		// -----------------------
		// display it
		this.view.display();
	}
	
	/**
	 * Add the component and data types nodes in the view.
	 */
	public void addNodes(PrefuseViewer prefuseViewer) {
		for (String tname : ASTActionDelegate.table.keySet()) {
			Information info = ASTActionDelegate.table.get(tname);
			boolean cmp = info.isComponentType();
			// may be short type name ? 
			// add provided interfaces and provided constants
			//System.out.println(" provided " + tname + "\n" + ASTActionDelegate.provided.getProvided(tname));
			Vector<String> all = ASTActionDelegate.provided.getProvided(tname);
			all.addAll(ASTActionDelegate.providedconstant.getProvided(tname));
			prefuseViewer.artefactAnalysis(tname, 10, cmp, all);
		}
	}
	// -----------------------------------------------------------------
	/**
	 * Add the composite edges in the view.
	 */
	public void addComposites(PrefuseViewer prefuseViewer) {
		for (String tname : ASTActionDelegate.table.keySet()) {
			Information info = ASTActionDelegate.table.get(tname);
			boolean cmp = info.isComponentType();
			// accessing IType need resolved
			if (info.isResolved()) {
				MyIType ity = info.getIbind();
				// component and class
				if (cmp && ity.isNature()) {
					//System.out.println("struc" + ity.getStructure());
					for (IVariableBinding ivb : ity.getStructure()) {
						String iname = ivb.getName();
						String itype = ivb.getType().getQualifiedName();
						// should check the creation first
						prefuseViewer.artefactAnalysis(itype, 5,
								ASTActionDelegate.table.get(itype).isComponentType());
						// create composite edge
						prefuseViewer.edgeCreation(PrefuseViewer.COMPOSITE, iname, tname, itype);
					}

				}
			}
		}
	}
	// -----------------------------------------------------------------
	public void addCommunications(PrefuseViewer prefuseViewer) {
		prefuseViewer.setTableCount();
		for (String em : this.communications.keySet()) {
			//String tmp = " Communications from " + em;
			InfoCom com = this.communications.get(em);
			for (String rec : com.keySet()) {
				// em was already and rec too
				// forget reflexive messages to simplify
				if (!em.equals(rec)) {
					Vector<IMethodBinding> vm = com.get(rec);
					// store the signature somewhere ...
					Vector<String> vecs = new Vector<String>();
					for (IMethodBinding m : vm) {
						// full name with m.toString()
						String rtype = m.getReturnType().getQualifiedName();
						String ptypes = "";
						for (ITypeBinding it : m.getParameterTypes()) {
							ptypes += it.getQualifiedName() + " ";
						}
						// communication creation
						vecs.add(m.getName() + "(" + ptypes + ") -> " + rtype);
						// one edge with all communications
						//System.out.println(" edgeComm from " + em + " to " + rec);
						prefuseViewer.edgeCommunication("communications", em, rec, vecs);
					} 
				}
			}
		} 
	}

	// -----------------------------------------------------------------
	/**
	 * Create subtyping edges from subinterfaces and subclasses.
	 */
	public void addSubtyping(PrefuseViewer prefuseViewer) {
		for (String tname : ASTActionDelegate.table.keySet()) {
			Information info = ASTActionDelegate.table.get(tname);
			MyIType ity = info.getIbind();
			// subclasses
			for (String sub : ity.getSubclasses()) {
				//System.out.println("addSubtyping from " + sub + " to " + tname);
				prefuseViewer.edgeCreation(PrefuseViewer.SUBTYPING, "subtyping", sub, tname);
			}
			// subinterfaces
			for (String sub : ity.getSubinterfaces()) {
				//System.out.println("addSubtyping from " + sub + " to " + tname);
				prefuseViewer.edgeCreation(PrefuseViewer.SUBTYPING, "subtyping", sub, tname);
			}

		}
	}
	// -----------------------------------------------------------------
}
