/*
 * 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.List;

import com.nomagic.magicdraw.actions.MDAction;
import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.core.GUILog;
import com.nomagic.magicdraw.core.Project;
import com.nomagic.magicdraw.ui.dialogs.MDDialogParentProvider;
import com.nomagic.ui.ProgressStatusRunner;
import com.nomagic.uml2.ext.magicdraw.auxiliaryconstructs.mdmodels.Model;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
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 UML4SOACompatibilityAction extends MDAction {

	private static final long serialVersionUID= 888444059710417869L;

	public UML4SOACompatibilityAction() {
		super("uml4soa_protocol_compliance_action", "Check 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();

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

		UMLElementSelectionDialog d= new UMLElementSelectionDialog(MDDialogParentProvider.getProvider().getDialogParent(), "UML4SOA",
				"Select two Protocol State Machines", psmList, psmList);
		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();
		ProtocolStateMachine right= (ProtocolStateMachine) d.getRight().getData();

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

		ProgressStatusRunner.runWithProgressStatus(worker, "Checking Protocol Compliance...", true, 0);

		Result result= worker.getResult();
		switch (result.getResultType()) {
			case ERROR: {
				MDUtil.error(result.getMessage());
				break;
			}
			case CHECK_OKAY: {
				MDUtil.info("The two protocols are compatible.");
				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;
				}

				// Transition is left or right, depending on aut.
				String transition= result.getProblematicTransition();

				// Left hand side automaton
				List<Element> p1= MDUtil.findProblematicMDElementsInPSM(left, result.getStateLeft(), aut == Side.LEFT ? transition : null);

				// Right hand side automaton
				List<Element> p2= MDUtil.findProblematicMDElementsInPSM(right, result.getStateRight(), aut == Side.RIGHT ? transition : null);

				GUILog guiLog= Application.getInstance().getGUILog();
				if (guiLog != null) {
					guiLog.showMessage("Message:" + result.getMessage());
					guiLog.showMessage("Left State:" + result.getStateLeft());
					guiLog.showMessage("Right State:" + result.getStateRight());
					guiLog.showMessage("Side:" + aut.name());
					guiLog.showMessage("Transition:" + transition);
				}

				UML4SOASemanticsMDPlugin.getCurrentInstance().addProblematicElements(p1);
				UML4SOASemanticsMDPlugin.getCurrentInstance().addProblematicElements(p2);

				MDUtil.error("The two protocols are not compatible: \n\n" + result.getMessage());

				break;
			}
		}
	}


}
