/******************************************************************************
 * Copyright (c) 2006, Intalio Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Intalio Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.stp.bpmn.diagram.actions;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.stp.bpmn.diagram.part.BpmnDiagramEditorPlugin;
import org.eclipse.ui.IActionDelegate;

/**
 * Abstract class to help creating actions designed to remove annotations
 * from diagram elements.
 * 
 * @author atoulme
 * @author <a href="http://www.intalio.com">&copy; Intalio, Inc.</a>
 */
public abstract class AbstractDeleteAnnotationAction implements IActionDelegate{

	 private ISelection _selection;
		private EModelElement selectedElt;
		private IGraphicalEditPart selectedPart;
	    
		/**
		 * Runs the deletion of the annotation with the source declared in
		 * the getAnnotationSource() method.
		 */
	    public void run(IAction action) {
	    	try {
	    	deleteAnnotation();
	    	} catch(ExecutionException e) {
	    		BpmnDiagramEditorPlugin.getInstance().getLog().log(
	    				new Status(IStatus.ERROR,
                                BpmnDiagramEditorPlugin.ID,
                                IStatus.ERROR,
	    						e.getMessage(),e));
	    	}
	    }

	    /**
	     * Deletes the annotation through a command.
	     * @throws ExecutionException
	     */
	    private void deleteAnnotation() throws ExecutionException {
	    	if (selectedElt.getEAnnotation(getAnnotationSource()) != null) {
	    		DestroyElementRequest request = new DestroyElementRequest(
	    				selectedElt.getEAnnotation(getAnnotationSource()),
	    				true);
	    		DestroyElementCommand command = new DestroyElementCommand(request);
	    		
	    			command.execute(null, null);
	    			selectedPart.refresh();
	    	}
	    }

	    
	    /**
	     * {@inheritDoc}
	     */
	    public void selectionChanged(IAction action, ISelection selection) {
	        if (!(selection instanceof IStructuredSelection)) {
	            action.setEnabled(false);
	            _selection = null;
	            return;
	        }
	        _selection = (IStructuredSelection)selection;
	        if (action != null) {
	            
	            updateSelectedEModelElement(_selection);
	            boolean ok = selectedElt != null && selectedPart != null;
	            action.setEnabled(ok);
	            if (ok) {
	            	System.err.println("about to update the text"); // REMOVE
	                action.setText(updateText(selectedElt));
	                action.setImageDescriptor(updateImage(selectedElt));
	                action.setDescription(updateDescription(selectedElt));
	                action.setToolTipText(updateToolTipText(selectedElt));
	            } else {
	            	action.setText(getDefaultLabel());
	            	action.setImageDescriptor(getDefaultImage());
	            	action.setDescription(getDefaultDescription());
	            	action.setToolTipText(getDefaultToolTipText());
	            }
	        }
	    }
	    
		/**
	     * @param elt
	     * @return the tooltip text for this action.
	     * Clients can override this method.
	     */
	    protected String updateToolTipText(EModelElement elt) {
			return null;
		}
	    /**
	     * 
	     * @param elt
	     * @return the description for the element.
	     * Clients can override this method.
	     */
		protected String updateDescription(EModelElement elt) {
			return null;
		}

		/**
	     * updates the label of the action 
	     * @param elt
	     * @return the text of the label for the action.
	     */
	    protected abstract String updateText(EModelElement elt);

	    /**
	     * Updates the image for the action label.
	     * @param elt
	     * @return the image for the action label or null.
	     */
	    protected abstract ImageDescriptor updateImage(EModelElement elt);
	    
	    /**
	     * 
	     * Updates The BPMN Model element and the selected edit part if it has an
	     * attached annotation with getAnnotationSource() source. null otherwise.
	     * May be overridden by clients to force more checks.
	     */
	    protected void updateSelectedEModelElement(ISelection selection) {
	        if (selection != null && selection instanceof IStructuredSelection) {
	            if (((IStructuredSelection) selection).getFirstElement() 
	            		instanceof IGraphicalEditPart) {
	            	IGraphicalEditPart part =
	            		(IGraphicalEditPart)
	            		((IStructuredSelection) selection).getFirstElement();
	            	if (part != null && part.getNotationView() != null) {
	            		EModelElement elt = (EModelElement)
	            		part.getNotationView().getElement();

	            		if (
	            	elt.getEAnnotation(getAnnotationSource()) != null) {
	            			selectedElt = elt;
	            			selectedPart = part;
	            			return;
	            		}
	            	}
	            }
	        }
	        selectedElt = null;
			selectedPart = null;
	    }
		
	    /**
	     * @return the string representing the source of the annotation.
	     * It is used in this class to know which annotation should be removed.
	     */
	    protected abstract String getAnnotationSource();
	    
	    /**
	     * Default label when no element is selected
	     * @return
	     */
	    protected String getDefaultLabel() {
	    	return "Delete Annotation";
	    }
	    
	    /**
	     * Default tool tip text when no element is selected
	     * @return
	     */
	    protected String getDefaultToolTipText() {
	    	return "No annotation are " +
			"attached to this element";
	    }
	    
	    /**
	     * Default image when no element is selected.
	     * @return
	     */
	    protected ImageDescriptor getDefaultImage() {
			return null;
		}
	    
	   /**
	    * Default description when no element is selected.
	    * @return
	    */
	    protected String getDefaultDescription() {
			return "No annotation are " +
			"attached to this element";
		}

	/**
	 * @return the selectedElt
	 */
	protected EModelElement getSelectedElt() {
		return selectedElt;
	}

	/**
	 * @param selectedElt the selectedElt to set
	 */
	protected void setSelectedElt(EModelElement selectedElt) {
		this.selectedElt = selectedElt;
	}

	/**
	 * @return the selectedPart
	 */
	public IGraphicalEditPart getSelectedPart() {
		return selectedPart;
	}

	/**
	 * @param selectedPart the selectedPart to set
	 */
	public void setSelectedPart(IGraphicalEditPart selectedPart) {
		this.selectedPart = selectedPart;
	}
}
