/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.texteditor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;

import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.quickassist.IQuickFixableAnnotation;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationAccessExtension;
import org.eclipse.jface.text.source.IAnnotationAccessExtension2;
import org.eclipse.jface.text.source.IAnnotationPresentation;
import org.eclipse.jface.text.source.ImageUtilities;
import org.eclipse.jface.text.source.projection.AnnotationBag;

import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.editors.text.EditorsPlugin;
import org.eclipse.ui.internal.texteditor.AnnotationType;
import org.eclipse.ui.internal.texteditor.AnnotationTypeHierarchy;


/**
 * Default class for accessing marker annotation properties.
 *
 * @since 2.1
 */
public class DefaultMarkerAnnotationAccess implements IAnnotationAccess, IAnnotationAccessExtension, IAnnotationAccessExtension2 {

	/**
	 * Constant for the unknown marker type.
	 *
	 * @deprecated As of 3.0, replaced by Annotation.TYPE_UNKNOWN
	 */
	@Deprecated
	public static final String UNKNOWN= Annotation.TYPE_UNKNOWN;

	/**
	 * Constant for the error system image.
	 * Value: <code>error</code>
	 *
	 * @since 3.0
	 */
	public static final String ERROR_SYSTEM_IMAGE= "error"; //$NON-NLS-1$
	/**
	 * Constant for the warning system image.
	 * Value: <code>warning</code>
	 *
	 * @since 3.0
	 */
	public static final String WARNING_SYSTEM_IMAGE= "warning"; //$NON-NLS-1$
	/**
	 * Constant for the info system image.
	 * Value: <code>info</code>
	 *
	 * @since 3.0
	 */
	public static final String INFO_SYSTEM_IMAGE= "info"; //$NON-NLS-1$
	/**
	 * Constant for the task system image.
	 * Value: <code>task</code>
	 *
	 * @since 3.0
	 */
	public static final String TASK_SYSTEM_IMAGE= "task"; //$NON-NLS-1$
	/**
	 * Constant for the bookmark system image.
	 * Value: <code>bookmark</code>
	 *
	 * @since 3.0
	 */
	public static final String BOOKMARK_SYSTEM_IMAGE= "bookmark"; //$NON-NLS-1$

	/**
	 * The mapping between external and internal symbolic system image names.
	 *
	 * @since 3.0
	 */
	private final static Map<String, String> MAPPING;

	static {
		MAPPING= new HashMap<>();
		MAPPING.put(ERROR_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_ERROR_TSK);
		MAPPING.put(WARNING_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_WARN_TSK);
		MAPPING.put(INFO_SYSTEM_IMAGE, ISharedImages.IMG_OBJS_INFO_TSK);
		MAPPING.put(TASK_SYSTEM_IMAGE, IDE.SharedImages.IMG_OBJS_TASK_TSK);
		MAPPING.put(BOOKMARK_SYSTEM_IMAGE, IDE.SharedImages.IMG_OBJS_BKMRK_TSK);
	}


	/**
	 * The marker annotation preferences.
	 *
	 * @deprecated As of 3.0, no replacement
	 */
	@Deprecated
	protected MarkerAnnotationPreferences fMarkerAnnotationPreferences;

	/**
	 * An optional quick assist processor.
	 *
	 * @since 3.2
	 */
	private IQuickAssistAssistant fQuickAssistAssistant;

	/**
	 * Returns a new default marker annotation access with the given preferences.
	 *
	 * @param markerAnnotationPreferences the marker annotation preference
	 * @deprecated As of 3.0, replaced by
	 *             {@link org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess#DefaultMarkerAnnotationAccess()}
	 */
	@Deprecated
	public DefaultMarkerAnnotationAccess(MarkerAnnotationPreferences markerAnnotationPreferences) {
		fMarkerAnnotationPreferences= markerAnnotationPreferences;
	}

	/**
	 * Creates a new default marker annotation access using the standard
	 * preference lookup strategy which is the one provided by the enclosing
	 * plug-in.
	 *
	 * @since 3.0
	 */
	public DefaultMarkerAnnotationAccess() {
	}

	@Override
	public void setQuickAssistAssistant(IQuickAssistAssistant assistant) {
		fQuickAssistAssistant= assistant;
	}

	/**
	 * Returns the annotation preference for the given annotation.
	 *
	 * @param annotation the annotation
	 * @return the annotation preference for the given annotation or <code>null</code>
	 */
	private AnnotationPreference getAnnotationPreference(Annotation annotation) {
		AnnotationPreferenceLookup lookup= getAnnotationPreferenceLookup();
		if (lookup != null)
			return lookup.getAnnotationPreference(annotation);
		return null;
	}

	/**
	 * Returns the annotation preference lookup used by this annotation access.
	 *
	 * @return the annotation preference lookup
	 * @since 3.0
	 */
	protected AnnotationPreferenceLookup getAnnotationPreferenceLookup() {
		return EditorsPlugin.getDefault().getAnnotationPreferenceLookup();
	}

	/**
	 * {@inheritDoc}
	 *
	 * @deprecated use <code>Annotation.getType()</code>
	 */

	@Deprecated
	@Override
	public Object getType(Annotation annotation) {
		return annotation.getType();
	}

	/**
	 * {@inheritDoc}
	 *
	 * @deprecated assumed to always return <code>true</code>
	 */
	@Deprecated
	@Override
	public boolean isMultiLine(Annotation annotation) {
		return true;
	}

	/**
	 * {@inheritDoc}
	 *
	 * @deprecated assumed to always return <code>true</code>
	 */
	@Deprecated
	@Override
	public boolean isTemporary(Annotation annotation) {
		return !annotation.isPersistent();
	}

	/*
	 * @see org.eclipse.jface.text.source.IAnnotationAccessExtension#getLabel(org.eclipse.jface.text.source.Annotation)
	 * @since 3.0
	 */
	@Override
	public String getTypeLabel(Annotation annotation) {
		AnnotationPreference preference= getAnnotationPreference(annotation);
		return preference != null ? preference.getPreferenceLabel() : null;
	}

	@Override
	public int getLayer(Annotation annotation) {
		if (annotation instanceof IAnnotationPresentation) {
			IAnnotationPresentation presentation= (IAnnotationPresentation) annotation;
			return presentation.getLayer();
		}

		AnnotationPreference preference= getAnnotationPreference(annotation);
		if (preference != null)
			return preference.getPresentationLayer();

		// backward compatibility, ignore exceptions, just return default layer
		try {

			Method method= annotation.getClass().getMethod("getLayer"); //$NON-NLS-1$
			Integer result= (Integer) method.invoke(annotation);
			return result.intValue();

		} catch (SecurityException x) {
		} catch (IllegalArgumentException x) {
		} catch (NoSuchMethodException x) {
		} catch (IllegalAccessException x) {
		} catch (InvocationTargetException x) {
		}

		return IAnnotationAccessExtension.DEFAULT_LAYER;
	}

	@Override
	public void paint(Annotation annotation, GC gc, Canvas canvas, Rectangle bounds) {

		if (annotation instanceof IAnnotationPresentation) {
			IAnnotationPresentation presentation= (IAnnotationPresentation) annotation;
			presentation.paint(gc, canvas, bounds);
			return;
		}

		AnnotationPreference preference= getAnnotationPreference(annotation);
		if (preference != null) {
			Object type= getType(annotation);
			String annotationType= (type == null ? null : type.toString());
			Image image= getImage(annotation, preference, annotationType);
			if (image != null) {
				ImageUtilities.drawImage(image, gc, canvas, bounds, SWT.CENTER, SWT.TOP);
				return;
			}
		}

		// backward compatibility, ignore exceptions, just don't paint
		try {

			Method method= annotation.getClass().getMethod("paint", new Class[] { GC.class, Canvas.class, Rectangle.class }); //$NON-NLS-1$
			method.invoke(annotation, new Object[] {gc, canvas, bounds });

		} catch (SecurityException x) {
		} catch (IllegalArgumentException x) {
		} catch (NoSuchMethodException x) {
		} catch (IllegalAccessException x) {
		} catch (InvocationTargetException x) {
		}
	}

	@Override
	public boolean isPaintable(Annotation annotation) {
		if (annotation instanceof IAnnotationPresentation)
			return true;

		AnnotationPreference preference= getAnnotationPreference(annotation);
		if (preference == null)
			return false;

		Object type= getType(annotation);
		String annotationType= (type == null ? null : type.toString());
		Image image= getImage(annotation, preference, annotationType);
		return image != null;
	}

	@Override
	public boolean isSubtype(Object annotationType, Object potentialSupertype) {
		AnnotationTypeHierarchy hierarchy= getAnnotationTypeHierarchy();
		return hierarchy.isSubtype(potentialSupertype.toString(), annotationType.toString());
	}

	@Override
	public Object[] getSupertypes(Object annotationType) {
		AnnotationTypeHierarchy hierarchy= getAnnotationTypeHierarchy();
		AnnotationType type= hierarchy.getAnnotationType(annotationType.toString());
		return type.getSuperTypes();
	}

	/**
	 * Returns the annotation type hierarchy used by this annotation access.
	 *
	 * @return the annotation type hierarchy
	 * @since 3.0
	 * @noreference This method is not intended to be referenced by clients.
	 */
	protected AnnotationTypeHierarchy getAnnotationTypeHierarchy() {
		return EditorsPlugin.getDefault().getAnnotationTypeHierarchy();
	}

	/**
	 * Translates the given symbolic image name into the shared image name as
	 * defined in {@link org.eclipse.ui.ISharedImages}.
	 * <p>
	 * The symbolic image name must be one of the
	 *
	 * @param symbolicImageName the symbolic image name, which must be one of
	 *            the valid values defined for the <code>symbolicIcon</code>
	 *            attribute in the
	 *            <code>org.eclipse.ui.editors.markerAnnotationSpecification</code>
	 *            extension point
	 * @return the shared image name
	 * @throws IllegalArgumentException if the <code>symbolicImageName</code> is not defined by the
	 * 			<code>org.eclipse.ui.editors.markerAnnotationSpecification</code> extension point
	 * @since 3.4
	 */
	public static String getSharedImageName(String symbolicImageName) {
		Assert.isLegal(symbolicImageName != null);
		String sharedImageName= MAPPING.get(symbolicImageName);
		Assert.isLegal(sharedImageName != null);
		return sharedImageName;
	}

	/**
	 * Returns the image for the given annotation and the given annotation preferences or
	 * <code>null</code> if there is no such image.
	 *
	 * @param annotation the annotation
	 * @param preference the annotation preference
	 * @param annotationType the annotation type
	 * @return the image or <code>null</code>
	 * @since 3.0
	 */
	private Image getImage(Annotation annotation, AnnotationPreference preference, String annotationType) {

		if (annotation instanceof AnnotationBag) {
			AnnotationBag bag= (AnnotationBag)annotation;
			if (!bag.isEmpty())
				annotation= bag.iterator().next();
		}

		ImageRegistry registry= EditorsPlugin.getDefault().getImageRegistry();

		IAnnotationImageProvider annotationImageProvider = preference.getAnnotationImageProvider();
		if (annotationImageProvider != null) {

			Image image= annotationImageProvider.getManagedImage(annotation);
			if (image != null)
				return image;

			String id= annotationImageProvider.getImageDescriptorId(annotation);
			if (id != null) {
				image= registry.get(id);
				if (image == null) {
					ImageDescriptor descriptor= annotationImageProvider.getImageDescriptor(id);
					registry.put(id, descriptor);
					image= registry.get(id);
				}
				return image;
			}
		}

		if (annotationType == null)
			return null;

		if (hasQuickFix(annotation)) {
			ImageDescriptor quickFixImageDesc= preference.getQuickFixImageDescriptor();
			if (quickFixImageDesc != null) {
				Image image= registry.get(quickFixImageDesc.toString());
				if (image == null) {
					registry.put(quickFixImageDesc.toString(), quickFixImageDesc);
					image= registry.get(quickFixImageDesc.toString());
				}
				if (image != null)
					return image;
			}
		}

		Image image= registry.get(annotationType);
		if (image == null) {
			ImageDescriptor descriptor= preference.getImageDescriptor();
			if (descriptor != null) {
				registry.put(annotationType, descriptor);
				image= registry.get(annotationType);
			} else {
				String symbolicImageName= preference.getSymbolicImageName();
				if (symbolicImageName != null) {
					String key= getSharedImageName(preference.getSymbolicImageName());
					if (key != null) {
						ISharedImages sharedImages= PlatformUI.getWorkbench().getSharedImages();
						image= sharedImages.getImage(key);
					}
				}
			}
		}
		return image;
	}

	/**
	 * Checks whether there's a quick assist assistant and if so,
	 * whether the assistant has a possible fix for the given
	 * annotation.
	 *
	 * @param annotation the annotation
	 * @return <code>true</code> if there is quick fix
	 * @since 3.2
	 */
	protected boolean hasQuickFix(Annotation annotation) {
		if (annotation instanceof IQuickFixableAnnotation) {
			IQuickFixableAnnotation quickFixableAnnotation= (IQuickFixableAnnotation)annotation;
			if (!quickFixableAnnotation.isQuickFixableStateSet())
				quickFixableAnnotation.setQuickFixable(fQuickAssistAssistant != null && fQuickAssistAssistant.canFix(annotation));
			return quickFixableAnnotation.isQuickFixable();
		}
		return false;
	}

}
