package transformation.associationtags;

import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.openapi.uml.PresentationElementsManager;
import com.nomagic.magicdraw.openapi.uml.ReadOnlyElementException;
import com.nomagic.magicdraw.openapi.uml.SessionManager;
import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement;
import com.nomagic.magicdraw.uml.symbols.shapes.ShapeElement;
import com.nomagic.uml2.ext.magicdraw.actions.mdbasicactions.CallBehaviorAction;
import com.nomagic.uml2.ext.magicdraw.activities.mdintermediateactivities.ActivityPartition;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Comment;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Diagram;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
import com.nomagic.uml2.impl.ElementsFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DiagramExtension {
	
	DiagramPresentationElement diagramPE;
	Diagram diagram;
	List<String> actionList = new ArrayList<String>();
	List<String> roleList = new ArrayList<String>();
	Map<String, List<String>> partitionActionsMap = new HashMap<String, List<String>>();
	
	/**
	 * Collects the names of actions on the UMLsec model and activity partition names as potential roles
	 * @param diagramPE    The UMLsec diagram
	 */
	public DiagramExtension(DiagramPresentationElement diagramPE) {
		
		this.diagramPE = diagramPE;
		this.diagram = diagramPE.getDiagram();
		
		Collection<Element> elements = diagram.getOwner().getOwnedElement();
		for (Element element : elements) {
			if (element instanceof CallBehaviorAction) {
				String actionName = ((CallBehaviorAction) element).getName();
				String partitionName = ((CallBehaviorAction) element).getInPartition().iterator().next().getName();
				
				// Collects the names of all actions
				actionList.add(actionName);
				
				// Maps the name of the action to the name of its partition
				if (partitionActionsMap.containsKey(partitionName) == false) {
					partitionActionsMap.put(partitionName, new ArrayList<String>());
				}
				partitionActionsMap.get(partitionName).add(actionName);
				
				// Collects the names of all activity partitions
				if (roleList.contains(partitionName) == false) {
					roleList.add(partitionName);
				}
			}
		}
	}

	/**
	 * 
	 * @return The Comment element on the UMLsec model, containing information on association tags
	 */
	public Comment getTagComment() {
		for (Element element : diagram.getOwnedElement()) {
			if (element.getClass().getName().equals("com.nomagic.uml2.ext.magicdraw.classes.mdkernel.impl.CommentImpl")) {
				return (Comment) element;
			}
		}
		return null;
	}
	
	/**
	 * Adds a comment to the UMLsec diagram, containing information on association tags
	 * @param tags List of UMLsec association tags
	 */
	public Comment addTagComment(List<AssociationTag> tags) {
		Diagram diagram = diagramPE.getDiagram();
		diagramPE.open();		
		SessionManager.getInstance().createSession("Create element");
		ElementsFactory ef = Application.getInstance().getProject().getElementsFactory();
		Comment comment = ef.createCommentInstance();
		comment.setOwner(diagram);
		
		// A visible comment is created on the diagram
		PresentationElementsManager PEMInstance = PresentationElementsManager.getInstance();
		try {
			ShapeElement commentShape = PEMInstance.createShapeElement(comment, diagramPE);
			int height = diagramPE.getBounds().height;
			int width = diagramPE.getBounds().width;
			commentShape.setLocation(width-150, height-150);
			commentShape.setAutosize(true);
			commentShape.setVisible(false);
		} catch (ReadOnlyElementException e1) {
			e1.printStackTrace();
		}
		SessionManager.getInstance().closeSession();
		return comment;
	}
	
	public List<String> getProtectedActionList() {
		return this.actionList;
	}
	
	public List<String> getRoleList () {
		return this.roleList;
	}
	
	public Map<String, List<String>> getPartitionActionsMap() {
		return this.partitionActionsMap;
	}
}
