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

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.nomagic.magicdraw.actions.ActionsConfiguratorsManager;
import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.core.Project;
import com.nomagic.magicdraw.core.project.ProjectEventListenerAdapter;
import com.nomagic.magicdraw.plugins.Plugin;
import com.nomagic.magicdraw.ui.DiagramSurfacePainter;
import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement;
import com.nomagic.magicdraw.uml.symbols.DiagramSurface;
import com.nomagic.magicdraw.uml.symbols.PresentationElement;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;

import eu.uml4soa.utbm.ui.md.UML4SOAMainMenuConfigurator;

public class UML4SOASemanticsMDPlugin extends Plugin {

	private static UML4SOASemanticsMDPlugin fgInstance;

	private static Object fLock= new Object();

	private boolean fIsInitialized= false;

	private List<Element> fProblematicElements= new ArrayList<Element>();

	protected DiagramSurfacePainter fPainter= new DiagramSurfacePainter() {
		public void paint(Graphics g, DiagramPresentationElement diagram) {
			g.setColor(Color.RED);
			// traverse all symbols in the diagram
			List<PresentationElement> symbols= diagram.getPresentationElements();
			for (int i= 0; i < symbols.size(); i++) {
				PresentationElement o= (PresentationElement) symbols.get(i);

				Element theModel= o.getElement();
				if (theModel != null && isProblematic(theModel)) {
					Rectangle bounds= o.getBounds();
					bounds.grow(3, 3);
					((Graphics2D) g).setStroke(new BasicStroke(3));
					((Graphics2D) g).draw(bounds);
				}
			}
		}

	};

	public UML4SOASemanticsMDPlugin() {
		super();
		synchronized (fLock) {
			fgInstance= this;
		}
	}

	private UML4SOASemanticsMDPlugin(boolean dummy) {
		super();
	}


	public static UML4SOASemanticsMDPlugin getCurrentInstance() {
		UML4SOASemanticsMDPlugin temp= null;
		synchronized (fLock) {

			if (fgInstance == null)
				fgInstance= new UML4SOASemanticsMDPlugin(true);
			temp= fgInstance;
		}
		return temp;
	}

	public synchronized void init() {


		fIsInitialized= true;
		ActionsConfiguratorsManager manager= ActionsConfiguratorsManager.getInstance();

		manager.addMainMenuConfigurator(new UML4SOAMainMenuConfigurator());

		Application.getInstance().addProjectEventListener(new ProjectEventListenerAdapter() {

			public void projectOpened(Project project) {

				// Add a paint listener to all opened diagrams of this project
				Collection<DiagramPresentationElement> diagrams= project.getDiagrams();
				for (DiagramPresentationElement diagram : diagrams) {
					addListener(diagram);
				}

				// If new ones are opened later on, add to those as well.
				project.addPropertyChangeListener(new PropertyChangeListener() {
					public void propertyChange(PropertyChangeEvent evt) {

						if (evt.getPropertyName().equals(Project.DIAGRAM_OPENED)) {
							// take active diagram - this will be the opened one
							DiagramPresentationElement diagram= Application.getInstance().getProject().getActiveDiagram();
							addListener(diagram);
						}
					}
				});
			}

			private void addListener(DiagramPresentationElement diagram) {
				// register custom painter for painting blue
				// rectangles around every Shape in the diagram
				// diagram.getDiagramSurface().removePainter(fPainter);
				if (diagram == null)
					return;

				if (diagram.getDiagramSurface() == null)
					return;

				diagram.getDiagramSurface().addPainter(fPainter);
			}

		});
	}

	private boolean isProblematic(Element theModel) {
		return fProblematicElements.contains(theModel);
	}

	public boolean close() {
		return true;
	}

	public boolean isSupported() {
		return true;
	}

	public synchronized boolean isInitialized() {
		return fIsInitialized;
	}

	public void addProblematicElements(List<Element> problematix) {
		fProblematicElements.addAll(problematix);

		refresh();
	}

	public void clearProblems() {
		fProblematicElements.clear();
		refresh();
	}

	private void refresh() {
		Collection<DiagramPresentationElement> diagrams= Application.getInstance().getProject().getDiagrams();
		for (DiagramPresentationElement diagramPresentationElement : diagrams) {

			DiagramSurface diagramSurface= diagramPresentationElement.getDiagramSurface();
			if (diagramSurface != null) {
				diagramSurface.repaint();
			}
		}
	}
}
