content: /**
   *  Copyright (c) 2013-2016 Angelo ZERR.
   *  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:
   *  Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
   */
  package tern.eclipse.ide.ui.hover;
  
  import java.util.Iterator;
  
  import org.eclipse.core.filebuffers.FileBuffers;
  import org.eclipse.core.filebuffers.ITextFileBufferManager;
  import org.eclipse.core.filebuffers.LocationKind;
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IPath;
  import org.eclipse.jface.text.IRegion;
  import org.eclipse.jface.text.ITextViewer;
  import org.eclipse.jface.text.Position;
  import org.eclipse.jface.text.source.Annotation;
  import org.eclipse.jface.text.source.IAnnotationModel;
  import org.eclipse.jface.text.source.ISourceViewer;
  import org.eclipse.ui.IEditorInput;
  import org.eclipse.ui.IStorageEditorInput;
  import org.eclipse.ui.editors.text.EditorsUI;
  import org.eclipse.ui.texteditor.AnnotationPreference;
  import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
  
  import tern.eclipse.ide.internal.ui.Trace;
  
  /**
   * Problem Hover used to display errors when mouse over a JS content which have
   * a tern error.
   *
   */
  public class ProblemTernHover extends AbstractTernHover {
  
  	private static final String ORG_ECLIPSE_WST_SSE_UI_TEMP = "org.eclipse.wst.sse.ui.temp.";
  	
  	private DefaultMarkerAnnotationAccess fAnnotationAccess = new DefaultMarkerAnnotationAccess();
  
  	@Override
  	public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
  		IPath path;
  		IAnnotationModel model;
  		if (textViewer instanceof ISourceViewer) {
  			path = null;
  			model = ((ISourceViewer) textViewer).getAnnotationModel();
  		} else {
  			// Get annotation model from file buffer manager
  			path = getEditorInputPath();
  			model = getAnnotationModel(path);
  		}
  		if (model == null)
  			return null;
  		try {
  			Iterator e = model.getAnnotationIterator();
  			int layer = -1;
  			String message = null;
  			while (e.hasNext()) {
  				Annotation a = (Annotation) e.next();
  				if (!isTernAnnotation(a)) {
  					continue;
  				}
  				AnnotationPreference preference = getAnnotationPreference(a);
  				// if (preference == null
  				// || !(preference.getTextPreferenceKey() != null
  				// /*
  				// * && fStore.getBoolean(preference
  				// * .getTextPreferenceKey()
  				// */)
  				// || (preference.getHighlightPreferenceKey() != null /*
  				// * &&
  				// * fStore
  				// * .
  				// * getBoolean
  				// * (
  				// * preference
  				// * .
  				// * getHighlightPreferenceKey
  				// * (
  				// * )
  				// * )
  				// * )
  				// */)) {
  				// continue;
  				// }
  
  				Position p = model.getPosition(a);
  
  				int l = fAnnotationAccess.getLayer(a);
  
  				if (l > layer
  						&& p != null
  						&& p.overlapsWith(hoverRegion.getOffset(),
  								hoverRegion.getLength())) {
  					String msg = a.getText();
  					if (msg != null && msg.trim().length() > 0) {
  						message = msg;
  						layer = l;
  					}
  				}
  			}
  			if (layer > -1) {
  				return formatMessage(message);
  			}
  
  		} finally {
  			try {
  				if (path != null) {
  					ITextFileBufferManager manager = FileBuffers
  							.getTextFileBufferManager();
  					manager.disconnect(path, LocationKind.NORMALIZE, null);
  				}
  			} catch (CoreException ex) {
  				Trace.trace(Trace.SEVERE, "Error while get problem info", ex);
  			}
  		}
  		return null;
  	}
  
  	/**
  	 * Returns true if the given annotation is a Tern Annotation and false
  	 * otherwise.
  	 * 
  	 * @param a
  	 *            annotation to check
  	 * @return true if the given annotation is a Tern Annotation and false
  	 *         otherwise.
  	 */
  	protected boolean isTernAnnotation(Annotation a) {
  		String type = a.getType();
  		// Annotation coming from WTP TernSourceValidator
  		return ((type != null && type
  				.startsWith(ORG_ECLIPSE_WST_SSE_UI_TEMP)));
  	}
  
  	private String formatMessage(String message) {
  		return message;
  	}
  
  	private IPath getEditorInputPath() {
  		if (getEditor() == null)
  			return null;
  
  		IEditorInput input = getEditor().getEditorInput();
  		if (input instanceof IStorageEditorInput) {
  			try {
  				return ((IStorageEditorInput) input).getStorage().getFullPath();
  			} catch (CoreException ex) {
  				Trace.trace(Trace.SEVERE, "Error while get editor input path",
  						ex);
  			}
  		}
  		return null;
  	}
  
  	private IAnnotationModel getAnnotationModel(IPath path) {
  		if (path == null)
  			return null;
  
  		ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
  		try {
  			manager.connect(path, LocationKind.NORMALIZE, null);
  		} catch (CoreException ex) {
  			Trace.trace(Trace.SEVERE, "Error while get annotation model", ex);
  			return null;
  		}
  
  		IAnnotationModel model = null;
  		try {
  			model = manager.getTextFileBuffer(path, LocationKind.NORMALIZE)
  					.getAnnotationModel();
  			return model;
  		} finally {
  			if (model == null) {
  				try {
  					manager.disconnect(path, LocationKind.NORMALIZE, null);
  				} catch (CoreException ex) {
  					Trace.trace(Trace.SEVERE,
  							"Error while get annotation model", ex);
  				}
  			}
  		}
  	}
  
  	/**
  	 * Returns the annotation preference for the given annotation.
  	 *
  	 * @param annotation
  	 *            the annotation
  	 * @return the annotation preference or <code>null</code> if none
  	 */
  	private AnnotationPreference getAnnotationPreference(Annotation annotation) {
  
  		if (annotation.isMarkedDeleted())
  			return null;
  		return EditorsUI.getAnnotationPreferenceLookup()
  				.getAnnotationPreference(annotation);
  	}
  }
  