/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Andreas Schmid, service@aaschmid.de - Locate test method even if it contains parameters - http://bugs.eclipse.org/343935
 *******************************************************************************/
package org.eclipse.jdt.internal.junit.ui;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;

import org.eclipse.jface.dialogs.MessageDialog;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.texteditor.ITextEditor;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;

import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
import org.eclipse.jdt.internal.junit.BasicElementLabels;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.model.TestCaseElement;
import org.eclipse.jdt.internal.junit.model.TestElement;

import org.eclipse.jdt.internal.ui.actions.SelectionConverter;

/**
 * Open a class on a Test method.
 */
public class OpenTestAction extends OpenEditorAction {

	private String fMethodName;
	private String[] fMethodParamTypes;
	private IMethod fMethod;
	private int fLineNumber= -1;

	private IType fType;

	public OpenTestAction(TestRunnerViewPart testRunnerPart, TestCaseElement testCase, String[] methodParamTypes) {
		this(testRunnerPart, testCase.getClassName(), extractRealMethodName(testCase), methodParamTypes, true);
		String trace= testCase.getTrace();
		if (trace != null) {
			String rawClassName= TestElement.extractRawClassName(testCase.getTestName());
			rawClassName= rawClassName.replaceAll("\\.", "\\\\."); //$NON-NLS-1$//$NON-NLS-2$
			rawClassName= rawClassName.replaceAll("\\$", "\\\\\\$"); //$NON-NLS-1$//$NON-NLS-2$
			Pattern pattern= Pattern.compile(FailureTrace.FRAME_PREFIX
					+ rawClassName + '.' + fMethodName
					+ "\\(.*:(\\d+)\\)"  //$NON-NLS-1$
			);
			Matcher matcher= pattern.matcher(trace);
			if (matcher.find()) {
				try {
					fLineNumber= Integer.parseInt(matcher.group(1));
				} catch (NumberFormatException e) {
					// continue
				}
			}
		}
	}

	public OpenTestAction(TestRunnerViewPart testRunner, String className) {
		this(testRunner, className, null, null, true);
	}

	public OpenTestAction(TestRunnerViewPart testRunner, String className, String method, String[] methodParamTypes, boolean activate) {
		super(testRunner, className, activate);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJUnitHelpContextIds.OPENTEST_ACTION);
		fMethodName= method;
		fMethodParamTypes= methodParamTypes;
	}

	private static String extractRealMethodName(TestCaseElement testCase) {
		//workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=334864 :
		if (testCase.isIgnored() && JavaConventions.validateJavaTypeName(testCase.getTestName(), JavaCore.VERSION_1_5, JavaCore.VERSION_1_5, null).getSeverity() != IStatus.ERROR) {
			return null;
		}

		//workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=275308 :
		String testMethodName= testCase.getTestMethodName();
		for (int i= 0; i < testMethodName.length(); i++) {
			if (!Character.isJavaIdentifierPart(testMethodName.charAt(i))) {
				return testMethodName.substring(0, i);
			}
		}
		return testMethodName;
	}

	@Override
	protected IJavaElement findElement(IJavaProject project, String className) throws JavaModelException {
		IType type= findType(project, className);
		if (type == null)
			return null;

		if (fMethodName == null) {
			fType= type;
			return type;
		}

		IMethod method= null;
		try {
			method= findMethod(type);
			if (method == null) {
				ITypeHierarchy typeHierarchy= type.newSupertypeHierarchy(null);
				IType[] supertypes= typeHierarchy.getAllSupertypes(type);
				for (IType supertype : supertypes) {
					method= findMethod(supertype);
					if (method != null)
						break;
				}
			}
		} catch (OperationCanceledException e) {
			// user cancelled the selection dialog - ignore and proceed
		}
		if (method == null) {
			if (fLineNumber < 0) {
				String title= JUnitMessages.OpenTestAction_dialog_title;
				String message= Messages.format(JUnitMessages.OpenTestAction_error_methodNoFound, BasicElementLabels.getJavaElementName(fMethodName));
				MessageDialog.openInformation(getShell(), title, message);
			}
			return type;
		}

		fMethod= method;
		return method;
	}

	private IMethod findMethod(IType type) {
		IStatus status= JavaConventionsUtil.validateMethodName(fMethodName, type);
		if (! status.isOK())
			return null;

		List<IMethod> foundMethods= new ArrayList<>();
		try {
			PlatformUI.getWorkbench().getProgressService().busyCursorWhile(monitor -> {
				String methodPattern= type.getFullyQualifiedName('.') + '.' + fMethodName;
				if (fMethodParamTypes != null && fMethodParamTypes.length > 0) {
					String paramTypes= Arrays.stream(fMethodParamTypes).map(paramType -> {
						try {
							return paramType= Signature.toString(paramType);
						} catch (IllegalArgumentException e1) {
							// return the paramType as it is
						}
						return paramType.replace('$', '.'); // for nested classes... See OpenEditorAction#findType also.
					}).collect(Collectors.joining(", ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					methodPattern+= paramTypes;
				} else {
					methodPattern+= "()"; //$NON-NLS-1$
				}
				int matchRule= SearchPattern.R_ERASURE_MATCH | SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
				SearchPattern searchPattern= SearchPattern.createPattern(methodPattern, IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, matchRule);
				if (searchPattern == null) {
					return;
				}
				SearchRequestor requestor= new SearchRequestor() {
					@Override
					public void acceptSearchMatch(SearchMatch match) throws CoreException {
						Object element= match.getElement();
						if (element instanceof IMethod) {
							foundMethods.add((IMethod) element);
						}
					}
				};
				SearchParticipant[] participants= new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() };
				IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { type });
				try {
					new SearchEngine().search(searchPattern, participants, scope, requestor, monitor);
				} catch (CoreException e2) {
					JUnitPlugin.log(e2);
				}
			});
		} catch (InvocationTargetException e) {
			JUnitPlugin.log(e);
		} catch (InterruptedException e) {
			// user cancelled
		}

		if (foundMethods.size() == 1) {
			return foundMethods.get(0);
		} else if (foundMethods.size() > 1) {
			IMethod method= openSelectionDialog(foundMethods);
			if (method == null) {
				throw new OperationCanceledException();
			}
			return method;
		}

		// search just by name and number of parameters, if method not found yet
		try {
			for (IMethod method : type.getMethods()) {
				String methodName= method.getElementName();
				if (fMethodName.equals(methodName)) {
					int numOfParams= method.getNumberOfParameters();
					int requiredNumOfParams= 0;
					if (fMethodParamTypes != null) {
						requiredNumOfParams= fMethodParamTypes.length;
					}
					if (numOfParams == requiredNumOfParams) {
						foundMethods.add(method);
					}
				}
			}
			if (foundMethods.isEmpty()) {
				return null;
			} else if (foundMethods.size() > 1) {
				IMethod method= openSelectionDialog(foundMethods);
				if (method == null) {
					throw new OperationCanceledException();
				}
				return method;
			} else {
				return foundMethods.get(0);
			}
		} catch (JavaModelException e) {
			// if type does not exist or if an exception occurs while accessing its resource => ignore (no method found)
		}

		return null;
	}

	private IMethod openSelectionDialog(List<IMethod> foundMethods) {
		IMethod[] elements= foundMethods.toArray(new IMethod[foundMethods.size()]);
		String title= JUnitMessages.OpenTestAction_dialog_title;
		String message= JUnitMessages.OpenTestAction_select_element;
		return (IMethod) SelectionConverter.selectJavaElement(elements, getShell(), title, message);
	}

	@Override
	protected void reveal(ITextEditor textEditor) {
		if (fLineNumber >= 0) {
			try {
				IDocument document= textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
				int lineOffset= document.getLineOffset(fLineNumber-1);
				int lineLength= document.getLineLength(fLineNumber-1);
				if (fMethod != null) {
					try {
						ISourceRange sr= fMethod.getSourceRange();
						if (sr == null || sr.getOffset() == -1
								|| lineOffset < sr.getOffset()
								|| sr.getOffset() + sr.getLength() < lineOffset + lineLength) {
							throw new BadLocationException();
						}
					} catch (JavaModelException e) {
						// not a problem
					}
				}
				textEditor.selectAndReveal(lineOffset, lineLength);
				return;
			} catch (BadLocationException x) {
				// marker refers to invalid text position -> do nothing
			}
		}
		if (fMethod != null) {
			try {
				ISourceRange range= fMethod.getNameRange();
				if (range != null && range.getOffset() >= 0)
					textEditor.selectAndReveal(range.getOffset(), range.getLength());
				return;
			} catch (JavaModelException e) {
				// not a problem
			}
		}
		if (fType != null) {
			try {
				ISourceRange range= fType.getNameRange();
				if (range != null && range.getOffset() >= 0)
					textEditor.selectAndReveal(range.getOffset(), range.getLength());
			} catch (JavaModelException e) {
				// not a problem
			}
		}
	}

}
