/*
 * This file has been developed at the University of Munich, Chair for Programming & Software Engineering.
 * 
 * This file is licensed under the Eclipse Public License (EPL) 1.0
 * 
 */
package eu.uml4soa.utbm.ui.md;

import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.List;

import com.nomagic.magicdraw.actions.MDAction;
import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.core.Project;
import com.nomagic.magicdraw.ui.dialogs.MDDialogParentProvider;
import com.nomagic.ui.ProgressStatusRunner;
import com.nomagic.uml2.ext.magicdraw.activities.mdfundamentalactivities.Activity;
import com.nomagic.uml2.ext.magicdraw.auxiliaryconstructs.mdmodels.Model;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
import com.nomagic.uml2.ext.magicdraw.commonbehaviors.mdbasicbehaviors.Behavior;
import com.nomagic.uml2.ext.magicdraw.statemachines.mdprotocolstatemachines.ProtocolStateMachine;

import eu.uml4soa.utbm.ui.md.UML4SOAServerSemanticsWorker.Result;
import eu.uml4soa.utbm.ui.md.UML4SOAServerSemanticsWorker.Side;
import eu.uml4soa.utbm.ui.md.api.ServerClientConstants;
import eu.uml4soa.utbm.ui.md.api.UML4SOASemanticsMDPlugin;
import eu.uml4soa.utbm.ui.md.ui.SelectableElement;
import eu.uml4soa.utbm.ui.md.ui.TheorySelectionDialog;
import eu.uml4soa.utbm.ui.md.ui.UMLElementSelectionDialog;

public class UML4SOARefinementAction extends MDAction {

	private static final long serialVersionUID= -308290885087927071L;

	public UML4SOARefinementAction() {
		super("uml4soa_refinement_action", "Check Implementation/Protocol Compliance...", null, null);
	}

	@Override
	public void actionPerformed(ActionEvent e) {

		// Find two protocols
		Project project= Application.getInstance().getProject();

		if (project == null) {
			MDUtil.error("No open project.");
			return;
		}

		Model model= project.getModel();

		if (model == null) {
			MDUtil.error("No model in current project.");
			return;
		}

		UML4SOASemanticsMDPlugin.getCurrentInstance().clearProblems();

		// State Machines
		List<SelectableElement> psmList= MDUtil.createPSMSelectableElementList(MDUtil.getAllProtocolStateMachines(model));

		// Orchestrations
		List<SelectableElement> orchList= MDUtil.createParticipantSelectableElementList(MDUtil.getAllParticipants(model));

		UMLElementSelectionDialog d= new UMLElementSelectionDialog(MDDialogParentProvider.getProvider().getDialogParent(), "UML4SOA",
				"Select a Protocol State Machine and an Implementation:", psmList, orchList);
		if (!d.open())
			return;


		TheorySelectionDialog dd= new TheorySelectionDialog(MDDialogParentProvider.getProvider().getDialogParent(), "Verification",
				"Please select a verification method.");
		if (!dd.open())
			return;

		String theory= dd.getSelectedCompatibility();

		ProtocolStateMachine left= (ProtocolStateMachine) d.getLeft().getData();
		com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class right= (com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class) d.getRight().getData();

		UML4SOAServerSemanticsWorker worker= new UML4SOAServerSemanticsWorker();
		worker.setMessage(ServerClientConstants.CHECKTYPE_REFINEMENT + "/" + theory);
		worker.setLeft(MDUtil.getMachineReadableName(left));
		worker.setRight(MDUtil.getMachineReadableName(right));

		ProgressStatusRunner.runWithProgressStatus(worker, "Checking Implementation Conformity...", true, 0);

		Result result= worker.getResult();
		switch (result.getResultType()) {
			case ERROR: {
				MDUtil.error("An error occurred: " + result.getMessage());
				break;
			}
			case CHECK_OKAY: {
				MDUtil.info("Verification successful -- the orchestration is an implementation of this protocol!");
				break;
			}
			case CHECK_WRONG: {

				// We can annotate if the problem is in fact a transition
				// problem.
				Side aut= result.getProblematicAutomaton();
				if (aut == null) {
					MDUtil.error("Result Automaton is null");
					return;
				}
				ProtocolStateMachine toAnnotate= null;
				String stateInProblemAutomaton;
				if (aut == Side.LEFT) {

					// The problematic side is the protocol.
					toAnnotate= left;
					stateInProblemAutomaton= result.getStateLeft();
					String transition= result.getProblematicTransition();
					final List<Element> problematix= MDUtil.findProblematicMDElementsInPSM(toAnnotate, stateInProblemAutomaton, transition);

					// Find the corresponding element also on the right-hand
					// side

					Activity av= null;
					Collection<Behavior> ownedBehavior= right.getOwnedBehavior();
					for (Behavior behavior : ownedBehavior) {
						if (behavior instanceof Activity)
							av= (Activity) behavior;
					}

					if (av != null) {
						String problematicStateInActivity= result.getStateRight();
						Collection<? extends Element> newz= MDUtil.findProblematicMDElementsInActivity(av, problematicStateInActivity, transition);

						// MDUtil.info("newz=" + toString(newz));

						problematix.addAll(newz);
					}

					UML4SOASemanticsMDPlugin.getCurrentInstance().addProblematicElements(problematix);

				} else {
					// The problematic side is the implementation
					// TODO other automaton.
				}

				MDUtil.error("This orchestration is not an implementation of this protocol: \n\n" + result.getMessage());
				break;
			}
		}

	}

	private String toString(Collection<? extends Element> newz) {
		StringBuffer b= new StringBuffer();
		for (Element element : newz) {
			b.append(element + " ");
		}
		return b.toString();
	}


}
