/*******************************************************************************
 * Copyright (c) 2008, 2017 xored software, Inc. 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:
 *     xored software, Inc. - initial API and Implementation (Alex Panchenko)
 *******************************************************************************/
package org.eclipse.dltk.ruby.testing.internal.testunit;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.expressions.CallExpression;
import org.eclipse.dltk.ast.expressions.StringLiteral;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.SourceRange;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchParticipant;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.SearchRequestor;
import org.eclipse.dltk.ruby.ast.RubyCallArgument;
import org.eclipse.dltk.ruby.core.utils.RubySyntaxUtils;
import org.eclipse.dltk.ruby.internal.debug.ui.console.RubyConsoleSourceModuleLookup;
import org.eclipse.dltk.ruby.testing.internal.AbstractRubyTestRunnerUI;
import org.eclipse.dltk.ruby.testing.internal.AbstractRubyTestingEngine;
import org.eclipse.dltk.ruby.testing.internal.AbstractTestingEngineValidateVisitor;
import org.eclipse.dltk.ruby.testing.internal.ResolverUtils;
import org.eclipse.dltk.ruby.testing.internal.RubyTestingPlugin;
import org.eclipse.dltk.testing.DLTKTestingMessages;
import org.eclipse.dltk.testing.TestElementResolution;
import org.eclipse.dltk.testing.model.ITestCaseElement;
import org.eclipse.dltk.testing.model.ITestSuiteElement;
import org.eclipse.osgi.util.NLS;

public class TestUnitTestRunnerUI extends AbstractRubyTestRunnerUI {

	private static final char CLASS_BEGIN = '(';
	private static final char CLASS_END = ')';

	/**
	 * @param testingEngine
	 */
	public TestUnitTestRunnerUI(AbstractRubyTestingEngine testingEngine, IScriptProject project) {
		super(testingEngine, project);
	}

	@Override
	public String getTestCaseLabel(ITestCaseElement caseElement, boolean full) {
		final String testName = caseElement.getTestName();
		int index = testName.lastIndexOf(CLASS_BEGIN);
		if (index > 0) {
			final int braceIndex = index;
			while (index > 0 && Character.isWhitespace(testName.charAt(index - 1))) {
				--index;
			}
			if (full) {
				int end = testName.length();
				if (end > braceIndex + 1 && testName.charAt(end - 1) == CLASS_END) {
					--end;
				}
				final String template = DLTKTestingMessages.TestSessionLabelProvider_testMethodName_className;
				return NLS.bind(template, testName.substring(braceIndex + 1, end), testName.substring(0, index));
			} else {
				return testName.substring(0, index);
			}
		} else {
			return testName;
		}
	}

	@Override
	public String getTestStartedMessage(ITestCaseElement caseElement) {
		final String testName = caseElement.getTestName();
		int index = testName.lastIndexOf(CLASS_BEGIN);
		if (index > 0) {
			int end = testName.length();
			if (end > index && testName.charAt(end - 1) == CLASS_END) {
				--end;
			}
			final String className = testName.substring(index + 1, end);
			while (index > 0 && Character.isWhitespace(testName.charAt(index - 1))) {
				--index;
			}
			final String method = testName.substring(0, index);
			return NLS.bind(DLTKTestingMessages.TestRunnerViewPart_message_started, className, method);
		} else {
			return testName;
		}
	}

	private static final String SHOULDA_TEST_PREFIX = "test:"; //$NON-NLS-1$

	@Override
	protected TestElementResolution resolveTestCase(ITestCaseElement testCase) {
		final String testName = testCase.getTestName();
		if (testName.length() == 0) {
			return null;
		}
		final int pos = testName.lastIndexOf(CLASS_BEGIN);
		if (!(pos > 0 && testName.charAt(testName.length() - 1) == CLASS_END)) {
			return null;
		}
		final String className = testName.substring(pos + 1, testName.length() - 1);
		if (!RubySyntaxUtils.isValidClass(className)) {
			return null;
		}
		final String methodName = testName.substring(0, pos).trim();
		if (RubySyntaxUtils.isRubyMethodName(methodName)) {
			final IMethod method = findMethod(className, methodName);
			if (method != null) {
				return new TestElementResolution(method, ResolverUtils.getSourceRange(method));
			}
		}
		final List<IType> types = findClasses(className);
		if (types == null) {
			return null;
		}
		if (methodName.startsWith(SHOULDA_TEST_PREFIX)) {
			String shouldName = methodName.substring(SHOULDA_TEST_PREFIX.length()).trim();
			if (shouldName.length() != 0 && shouldName.charAt(shouldName.length() - 1) == '.') {
				shouldName = shouldName.substring(0, shouldName.length() - 1).trim();
			}
			if (shouldName.length() != 0) {
				final Set<IFile> resources = new HashSet<>();
				for (Iterator<IType> i = types.iterator(); i.hasNext();) {
					final IType type = i.next();
					final IResource resource = type.getResource();
					if (resource != null && resource instanceof IFile) {
						resources.add((IFile) resource);
					}
				}
				if (resources.isEmpty()) {
					return null;
				}
				for (Iterator<IFile> i = resources.iterator(); i.hasNext();) {
					final ISourceModule module = (ISourceModule) DLTKCore.create(i.next());
					final TestElementResolution resolution = findShould(module, className, shouldName);
					if (resolution != null) {
						return resolution;
					}
				}
			}
		}
		return null;
	}

	private static class ShouldLocator extends AbstractTestingEngineValidateVisitor {

		private static final String TWO_COLONS = "::"; //$NON-NLS-1$

		private final String className;
		private final String shouldName;

		private ISourceRange range = null;

		/**
		 * @param className
		 * @param shouldName
		 */
		public ShouldLocator(String className, String shouldName) {
			this.className = className;
			this.shouldName = shouldName;
		}

		final Stack<Boolean> typeMatches = new Stack<>();

		@Override
		public boolean visit(TypeDeclaration s) throws Exception {
			final String enclosingName = s.getEnclosingTypeName();
			final String fullName;
			if (enclosingName.length() == 0) {
				fullName = s.getName();
			} else {
				fullName = enclosingName.replaceAll("\\$", TWO_COLONS) + TWO_COLONS + s.getName(); //$NON-NLS-1$
			}
			typeMatches.push(Boolean.valueOf(className.equals(fullName)));
			return true;
		}

		@Override
		public boolean endvisit(TypeDeclaration s) throws Exception {
			typeMatches.pop();
			return true;
		}

		private boolean isMatchedType() {
			for (int i = 0, size = typeMatches.size(); i < size; ++i) {
				Boolean value = typeMatches.get(i);
				if (value.booleanValue()) {
					return true;
				}
			}
			return false;
		}

		final Stack<CallExpression> calls = new Stack<>();

		@Override
		public boolean visitGeneral(ASTNode node) throws Exception {
			if (isMatchedType() && range == null) {
				if (node instanceof CallExpression) {
					final CallExpression call = (CallExpression) node;
					if (isMethodCall(call, ShouldaUtils.METHODS) && call.getArgs().getChilds().size() >= 1) {
						final Object arg0 = call.getArgs().getChilds().get(0);
						if (arg0 instanceof RubyCallArgument) {
							final RubyCallArgument callArg = (RubyCallArgument) arg0;
							if (callArg.getValue() instanceof StringLiteral) {
								calls.push(call);
								if (isShouldMatched()) {
									range = new SourceRange(call.sourceStart(),
											callArg.sourceEnd() - call.sourceStart());
								}
							}
						}
					}
				}
			}
			return super.visitGeneral(node);
		}

		/**
		 * @return
		 */
		private boolean isShouldMatched() {
			if (isShouldMatched(shouldName)) {
				return true;
			}
			final String noTestClassName = className.replaceAll("Test", Util.EMPTY_STRING); //$NON-NLS-1$
			if (startsWith(shouldName, noTestClassName)) {
				return isShouldMatched(shouldName.substring(noTestClassName.length()).trim());
			}
			return false;
		}

		private boolean startsWith(final String value, final String substring) {
			return value.length() > substring.length() && value.startsWith(substring)
					&& Character.isWhitespace(value.charAt(substring.length()));
		}

		/**
		 * @param value
		 * @return
		 */
		private boolean isShouldMatched(String value) {
			for (int i = 0; i < calls.size(); ++i) {
				final CallExpression call = calls.get(i);
				if (ShouldaUtils.SHOULD.equals(call.getName())) {
					if (!startsWith(value, ShouldaUtils.SHOULD)) {
						return false;
					}
					value = value.substring(ShouldaUtils.SHOULD.length()).trim();
					final RubyCallArgument callArg = (RubyCallArgument) call.getArgs().getChilds().get(0);
					final String literal = ((StringLiteral) callArg.getValue()).getValue();
					if (value.equals(literal)) {
						return true;
					}
				} else if (ShouldaUtils.CONTEXT.equals(call.getName())) {
					final RubyCallArgument callArg = (RubyCallArgument) call.getArgs().getChilds().get(0);
					final String literal = ((StringLiteral) callArg.getValue()).getValue().trim();
					if (!startsWith(value, literal)) {
						return false;
					}
					value = value.substring(literal.length()).trim();
				}
			}
			return false;
		}

		@Override
		public void endvisitGeneral(ASTNode node) throws Exception {
			if (!calls.isEmpty() && calls.peek() == node) {
				calls.pop();
			}
			super.endvisitGeneral(node);
		}
	}

	/**
	 * @param module
	 * @param className
	 * @param shouldName
	 * @return
	 */
	private TestElementResolution findShould(ISourceModule module, String className, String shouldName) {
		final ModuleDeclaration declaration = ResolverUtils.parse(module);
		if (declaration != null) {
			try {
				final ShouldLocator locator = new ShouldLocator(className, shouldName);
				declaration.traverse(locator);
				if (locator.range != null) {
					final ISourceRange range = ResolverUtils.adjustRange(module.getSource(), locator.range);
					return new TestElementResolution(module, range);
				}
			} catch (Exception e) {
				final String msg = "Error in findShould()"; //$NON-NLS-1$
				RubyTestingPlugin.error(msg, e);
			}
		}
		return null;
	}

	@Override
	protected TestElementResolution resolveTestSuite(ITestSuiteElement element) {
		final String className = element.getSuiteTypeName();
		if (RubySyntaxUtils.isValidClass(className)) {
			final List<IType> types = findClasses(className);
			if (types != null) {
				final IType type = types.get(0);
				return new TestElementResolution(type, ResolverUtils.getSourceRange(type));
			}
		}
		return null;
	}

	private static final class TypeSearchRequestor extends SearchRequestor {
		final List<IType> types = new ArrayList<>();

		@Override
		public void acceptSearchMatch(SearchMatch match) throws CoreException {
			types.add((IType) match.getElement());
		}
	}

	private static final class MethodRequestor extends SearchRequestor {
		IMethod method = null;

		@Override
		public void acceptSearchMatch(SearchMatch match) throws CoreException {
			method = (IMethod) match.getElement();
		}
	}

	/**
	 * @param className
	 * @param methodName
	 * @return
	 */
	private IMethod findMethod(String className, String methodName) {
		final IDLTKSearchScope scope = getSearchScope();
		final String sPattern = className + "::" + methodName; //$NON-NLS-1$
		SearchPattern pattern = SearchPattern.createPattern(sPattern, IDLTKSearchConstants.METHOD,
				IDLTKSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
				scope.getLanguageToolkit());
		try {
			final MethodRequestor requestor = new MethodRequestor();
			new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
					scope, requestor, null);
			return requestor.method;
		} catch (CoreException e) {
			final String msg = "Error in findMethod({0}::{1})"; //$NON-NLS-1$
			RubyTestingPlugin.error(NLS.bind(msg, className, methodName), e);
		}
		return null;
	}

	/**
	 * @param className
	 */
	private List<IType> findClasses(String className) {
		final IDLTKSearchScope scope = getSearchScope();
		SearchPattern pattern = SearchPattern.createPattern(className, IDLTKSearchConstants.TYPE,
				IDLTKSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
				scope.getLanguageToolkit());
		try {
			final TypeSearchRequestor requestor = new TypeSearchRequestor();
			new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
					scope, requestor, null);
			if (!requestor.types.isEmpty()) {
				return requestor.types;
			}
		} catch (CoreException e) {
			final String msg = "Error in findClasses({0})"; //$NON-NLS-1$
			RubyTestingPlugin.error(NLS.bind(msg, className), e);
		}
		return null;
	}

	private static final String[] TEST_UNIT = { "test", "unit" }; //$NON-NLS-1$ //$NON-NLS-2$

	private boolean testFragmentPath(IPath fragmentPath, IPath path) {
		if (pathEquality.isPrefixOf(fragmentPath, path)
				&& path.segmentCount() > fragmentPath.segmentCount() + TEST_UNIT.length) {
			for (int j = 0; j < TEST_UNIT.length; ++j) {
				if (!TEST_UNIT[j].equals(path.segment(fragmentPath.segmentCount() + j))) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	private static String buildRegex() {
		final String slash = "[\\\\/]"; //$NON-NLS-1$
		return slash + "gems" + slash + "Shoulda-[\\w\\.]+" + slash + "lib" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ slash;
	}

	private static final Pattern GEM_SHOULDA_LIB = Pattern.compile(buildRegex());

	@Override
	protected boolean selectLine(String line) {
		final String filename = extractFileName(line);
		if (filename == null) {
			return true;
		}
		if (filename.endsWith(TestUnitTestingEngine.TEST_UNIT_RUNNER)) {
			return false;
		}
		if (GEM_SHOULDA_LIB.matcher(filename).find()) {
			return false;
		}
		final IPath path = new Path(filename);
		try {
			final IProjectFragment[] fragments = project.getProjectFragments();
			for (int i = 0; i < fragments.length; ++i) {
				final IProjectFragment fragment = fragments[i];
				if (fragment.isExternal()
						&& testFragmentPath(EnvironmentPathUtils.getLocalPath(fragment.getPath()), path)
						&& RubyConsoleSourceModuleLookup.isIncluded(fragment, path)) {
					return false;
				}
			}
		} catch (ModelException e) {
			return true;
		}
		return true;
	}
}
