package transformation.wizards;

import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.core.Project;
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.ui.actions.DefaultDiagramAction;
import com.nomagic.magicdraw.ui.dialogs.MDDialogParentProvider;
import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement;
import com.nomagic.magicdraw.uml.symbols.PresentationElement;
import com.nomagic.magicdraw.uml.symbols.shapes.NoteView;
import com.nomagic.magicdraw.uml.symbols.shapes.ShapeElement;
import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper;
import com.nomagic.uml2.ext.magicdraw.classes.mdassociationclasses.AssociationClass;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Property;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Type;

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

import javax.swing.JOptionPane;

public class SecureUML_Wizard {
	
	ShapeElement note;
	DiagramPresentationElement classDiagramPE;
	PresentationElementsManager PEMInstance;

	/**
     * Creates a note on the model with a list of missing elements.
     */
	public SecureUML_Wizard() {
		
		PEMInstance = PresentationElementsManager.getInstance();
		classDiagramPE = Application.getInstance().getProject().getActiveDiagram();
		
		SessionManager.getInstance().createSession("Create element");
		
		NoteView note = null;
		
		// Looks for an existing note element
		for (PresentationElement element : classDiagramPE.getPresentationElements()) {
			if (element instanceof NoteView) {
				note = (NoteView)element;
			}
		}
		
		// If none exist, creates a new note
		if (note == null) {
			try {
				note = (NoteView)(PEMInstance.createNote(classDiagramPE));
				note.setLocation(580, 500);
				note.setSize(200, 200);
			}
			catch (ReadOnlyElementException e) {
				JOptionPane.showMessageDialog(null, "Read-only element found, cannot create help note");
			}
		}
		
		// Adds text to note
		String noteText = validate();
		if (noteText != "") {
			note.setName(noteText);
		}
		SessionManager.getInstance().closeSession();
		
		// Makes the project saveable
		Application.getInstance().getProject().setDirty(true);
	}

    /**
     * Validates the diagram to see which elements are missing
     * 
     * @return List of elements missing from a complete SecureUML model
     */
	private String validate() {
		
	    // Lists of classes with no attributes, associations with no end names and attributes with no types
		List<String> attributelessClasses = new ArrayList<String>();
		List<List<Type>> endnamelessAssociations = new ArrayList<List<Type>>();
		List<String> typelessAttributes = new ArrayList<String>();
		
		for (Element element : classDiagramPE.getActualElement().getOwner().getOwnedElement()) {
		    // For each class on the diagram sees if it has any attributes
		    if (StereotypesHelper.getAppliedStereotypeByString(element, "secuml.resource") != null &&
					 element instanceof com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class) {
			
				 com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class classElement = 
					 (com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class) element;
				 
				 boolean hasAttributes = false;
				 for (Property attribute : classElement.getOwnedAttribute()) {
					 if (attribute.getName() != null && attribute.getName().equals("") == false) {
						 hasAttributes = true;
						 break;
					 }
				 }
				 
				 if (!hasAttributes) {
					 attributelessClasses.add(classElement.getName());
				 }
			 }
			
			if (StereotypesHelper.getAppliedStereotypeByString(element, "secuml.permission") != null &&
					element instanceof AssociationClass) {
			
			    // For each permission sees if it has end names
				AssociationClass associationClassElement = (AssociationClass) element;
				for (Property associationEnd : associationClassElement.getMemberEnd()) {
					if (associationEnd.getName() == null || associationEnd.getName().equals("")) {
						endnamelessAssociations.add(associationClassElement.getEndType());
						break;
					}
				}
				
				// For each permission also sees if its attributes have types
				for (Property attribute : associationClassElement.getAttribute()) {
					if (attribute.getType() == null) {
						typelessAttributes.add(attribute.getName());
						break;
					}
				}
			}
		}
		
		String returnString = "";
		
		if (attributelessClasses.size() != 0) {
			returnString += "* The following classes \nwith the stereotype <<secureuml.resource>>" +
					" \nhave no attributes:";
			for (String className : attributelessClasses) {
				returnString += "\n" + className;
			}
		}
		
		if (endnamelessAssociations.size() != 0) {
			returnString += "\n\n* Associations between the following \nclasses are missing end names:";
			for (List<Type> classPair : endnamelessAssociations) {
				returnString += "\n" + classPair.get(0).getName() + " - " + classPair.get(1).getName();
			}
		}
		
		if (typelessAttributes.size() != 0) {
			returnString += "\n\n* The following attributes of \npermission classes are missing action types:";
			for (String attributeName : typelessAttributes) {
				returnString += "\n" + attributeName;
			}
		}
		
		if (returnString.equals("")) {
			returnString += "Nothing could be found missing, diagram is OK.";
		}
		
		returnString += "\n\nYou may wish to complete the diagram with some authorization constraints.";
		
		return returnString;
	}
}
