package edu.kit.iti.formal.pse.worthwhile.util;

import static edu.kit.iti.formal.pse.worthwhile.util.WorthwhileConstants.MARKER_FAILED_STATEMENT;
import static edu.kit.iti.formal.pse.worthwhile.util.WorthwhileConstants.MARKER_SUCCEEDED_STATEMENT;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

import edu.kit.iti.formal.pse.worthwhile.model.ast.ASTNode;

/**
 * Helper class for setting markers in a Worthwhile file.
 * 
 * @author Joachim
 * 
 */
public class WorthwhileMarkerHelper {

	/**
	 * The resource to set the markers in.
	 */
	private final IResource resource;

	/**
	 * Creates a new instance of the {@link WorthwhileMarkerHelper} class.
	 * 
	 * @param resource
	 *                The resource to set the markers in.
	 */
	public WorthwhileMarkerHelper(final IResource resource) {
		if (resource == null) {
			throw new IllegalArgumentException("Resource may not be null");
		}

		this.resource = resource;
	}

	/**
	 * Clears all Worthwhile markers in the resource.
	 */
	public final void clearMarkers() {
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
				@Override
				public void run(final IProgressMonitor monitor) throws CoreException {
					resource.deleteMarkers(MARKER_FAILED_STATEMENT, true, IResource.DEPTH_INFINITE);
					resource.deleteMarkers(MARKER_SUCCEEDED_STATEMENT, true, IResource.DEPTH_INFINITE);
				}
			};
			runnable.run(null);
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Marks a statement as failed (e.g. an assertion).
	 * 
	 * @param statement
	 *                The statement to mark as failed.
	 * @param message
	 *                The message to mark the statement with.
	 */
	public final void markFailedStatement(final ASTNode statement, final String message) {
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
				@Override
				public void run(final IProgressMonitor monitor) throws CoreException {
					// Create a new marker
					IMarker marker = createMarker(statement, MARKER_FAILED_STATEMENT);
					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
					marker.setAttribute(IMarker.MESSAGE, message);
				}
			};
			runnable.run(null);
		} catch (CoreException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Marks a statement as succeeded (e.g. an assertion).
	 * 
	 * @param statement
	 *                The statement to mark as succeeded.
	 * @param message
	 *                The message to mark the statement with.
	 */
	public final void markSucceededStatement(final ASTNode statement, final String message) {
		try {
			IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
				@Override
				public void run(final IProgressMonitor monitor) throws CoreException {
					// Create a new marker
					IMarker marker = createMarker(statement, MARKER_SUCCEEDED_STATEMENT);
					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO);
					marker.setAttribute(IMarker.MESSAGE, message);
				}
			};
			runnable.run(null);
		} catch (CoreException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Creates a marker in the specified resource.
	 * 
	 * @param statement
	 *                The statement to mark in the resource.
	 * @param markerType
	 *                The type of the marker
	 * @return The created marker.
	 * @throws CoreException
	 *                 if the marker cannot be created.
	 */
	private IMarker createMarker(final ASTNode statement, final String markerType) throws CoreException {
		// Get the position of the node in the source file.
		int line = NodeHelper.getLine(statement);
		int offset = NodeHelper.getOffset(statement);
		int length = NodeHelper.getLength(statement);

		// Create a new marker
		IMarker marker = this.resource.createMarker(markerType);
		marker.setAttribute(IMarker.LINE_NUMBER, line);
		marker.setAttribute(IMarker.CHAR_START, offset);
		marker.setAttribute(IMarker.CHAR_END, offset + length);

		return marker;
	}

}

@@ -1505,32 +1505,53 @@
 STATEMENT, true,
+%0A%09%09%09%09%09               
  IResource.DEPTH
@@ -3678,16 +3678,27 @@
 osition 
+and length 
 of the n
@@ -3721,16 +3721,111 @@
 e file.%0A
+%09%09// Do not include trailing whitespace to prevent the marker from running into the next line.%0A
 %09%09int li
@@ -3923,16 +3923,26 @@
 ength = 
+trimRight(
 NodeHelp
@@ -3951,14 +3951,12 @@
 .get
-Length
+Text
 (sta
@@ -3962,16 +3962,26 @@
 atement)
+).length()
 ;%0A%0A%09%09// 
@@ -4219,16 +4219,16 @@
 ngth);%0A%0A
-
 %09%09return
@@ -4240,10 +4240,352 @@
 er;%0A%09%7D%0A%0A
+%09/**%0A%09 * Removes trailing whitespace from a string.%0A%09 * %0A%09 * http://forums.devshed.com/java-help-9/how-to-remove-leading-white-spaces-from-a-string-579116.html%0A%09 * %0A%09 * @param s%0A%09 *                The string%0A%09 * @return The right-trimmed string.%0A%09 */%0A%09private static String trimRight(final String s) %7B%0A%09%09return s.replaceAll(%22%5C%5Cs+$%22, %22%22);%0A%09%7D%0A%0A
 %7D%0A

Fix #42: Succeeded/failed statement markers run into next line