/*******************************************************************************
 * Copyright (c) 2005, 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
 *******************************************************************************/
package org.eclipse.jdt.internal.launching;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IOrdinaryClassFile;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;

/**
 * Property tester for context launching menu.
 *
 * @since 3.2
 */
public class JavaLaunchableTester extends PropertyTester {

	/**
	 * name for the "has main" property
	 */
	private static final String PROPERTY_HAS_MAIN = "hasMain"; //$NON-NLS-1$

	/**
	 * name for the "has method" property
	 */
	private static final String PROPERTY_HAS_METHOD = "hasMethod"; //$NON-NLS-1$

	/**
	 * name for the "has method with annotation" property
	 */
	private static final String PROPERTY_HAS_METHOD_WITH_ANNOTATION = "hasMethodWithAnnotation"; //$NON-NLS-1$

	/**
	 * name for the "has type with annotation" property
	 */
	private static final String PROPERTY_HAS_TYPE_WITH_ANNOTATION = "hasTypeWithAnnotation"; //$NON-NLS-1$

	/**
	 * name for the "extends class" property
	 */
	private static final String PROPERTY_EXTENDS_CLASS = "extendsClass"; //$NON-NLS-1$

	/**
	 * "is container" property
	 */
	private static final String PROPERTY_IS_CONTAINER = "isContainer"; //$NON-NLS-1$

	/**
	 * "is package fragment" property
	 * @since 3.3
	 */
	private static final String PROPERTY_IS_PACKAGE_FRAGMENT = "isPackageFragment"; //$NON-NLS-1$

	/**
	 * "is package fragment root" property
	 * @since 3.3
	 */
	private static final String PROPERTY_IS_PACKAGE_FRAGMENT_ROOT = "isPackageFragmentRoot"; //$NON-NLS-1$

	/**
	 * name for the PROPERTY_PROJECT_NATURE property
	 */
	private static final String PROPERTY_PROJECT_NATURE = "hasProjectNature"; //$NON-NLS-1$

	/**
	 * name for the "extends interface" property
	 */
	private static final String PROPERTY_EXTENDS_INTERFACE = "extendsInterface"; //$NON-NLS-1$

	/**
	 * name for the PROPERTY_HAS_SWT_ON_PATH property
	 */
	private static final String PROPERTY_BUILDPATH_REFERENCE = "buildpathReference"; //$NON-NLS-1$

    /**
     * Map of modifier text to corresponding flag (Integer)
     */
    private static Map<String, Integer> fgModifiers = new HashMap<>();

    private static final int FLAGS_MASK= Flags.AccPublic | Flags.AccProtected | Flags.AccPrivate | Flags.AccStatic
    	| Flags.AccFinal | Flags.AccSynchronized | Flags.AccAbstract | Flags.AccNative;


    static {
        fgModifiers.put("public",       new Integer(Flags.AccPublic)); //$NON-NLS-1$
        fgModifiers.put("protected",    new Integer(Flags.AccProtected)); //$NON-NLS-1$
        fgModifiers.put("private",      new Integer(Flags.AccPrivate)); //$NON-NLS-1$
        fgModifiers.put("static",       new Integer(Flags.AccStatic)); //$NON-NLS-1$
        fgModifiers.put("final",        new Integer(Flags.AccFinal)); //$NON-NLS-1$
        fgModifiers.put("synchronized", new Integer(Flags.AccSynchronized)); //$NON-NLS-1$
        fgModifiers.put("abstract",     new Integer(Flags.AccAbstract)); //$NON-NLS-1$
        fgModifiers.put("native",       new Integer(Flags.AccNative)); //$NON-NLS-1$
    }

	/**
	 * gets the type of the IJavaElement
	 * @param element the element to inspect
	 * @return the type
	 */
	private IType getType(IJavaElement element) {
        IType type = null;
        if (element instanceof ICompilationUnit) {
            type= ((ICompilationUnit) element).findPrimaryType();
        }
		else if (element instanceof IOrdinaryClassFile) {
			type = ((IOrdinaryClassFile) element).getType();
        }
        else if (element instanceof IType) {
            type = (IType) element;
        }
        else if (element instanceof IMember) {
            type = ((IMember)element).getDeclaringType();
        }
        return type;
    }

	/**
	 * Determines is the java element contains a main method.
	 *
	 * @param element the element to check for the method
	 * @return true if the method is found in the element, false otherwise
	 */
	private boolean hasMain(IJavaElement element) {
		try {
            IType type = getType(element);
            if(type != null && type.exists()) {
				if(hasMainMethod(type)) {
					return true;
				}
				//failed to find in public type, check static inner types
				IJavaElement[] children = type.getChildren();
				for(int i = 0; i < children.length; i++) {
					if(hasMainInChildren(getType(children[i]))) {
						return true;
					}
				}
            }
		}
		catch (JavaModelException e) {}
		catch (CoreException ce){}
		return false;
	}

	/**
	 * Returns if the specified <code>IType</code> has a main method
	 * @param type the type to inspect for a main type
	 * @return true if the specified type has a main method, false otherwise
	 * @throws JavaModelException if there is an error in the backing Java model
	 * @since 3.3
	 */
	private boolean hasMainMethod(IType type) throws JavaModelException {
		IMethod[] methods = type.getMethods();
		for (int i= 0; i < methods.length; i++) {
			if(methods[i].isMainMethod()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * This method asks the specified <code>IType</code> if it has a main method, if not it recurses through all of its children
	 * When recursing we only care about child <code>IType</code>s that are static.
	 * @param type the <code>IType</code> to inspect for a main method
	 * @return true if a main method was found in specified <code>IType</code>, false otherwise
	 * @throws CoreException if there is an error
	 * @since 3.3
	 */
	private boolean hasMainInChildren(IType type) throws CoreException {
		if(type.isClass() & Flags.isStatic(type.getFlags())) {
			if(hasMainMethod(type)) {
				return true;
			}
			IJavaElement[] children = type.getChildren();
			for(int i = 0; i < children.length; i++) {
				if(children[i].getElementType() == IJavaElement.TYPE) {
					return hasMainInChildren((IType) children[i]);
				}
			}
		}
		return false;
	}

	/**
	 * Determines is the java element contains a specific method.
     * <p>
     * The syntax for the property tester is of the form: methodname,
     * signature, modifiers.
	 * </p>
     * <ol>
     * <li>methodname - case sensitive method name, required. For example,
     *  <code>toString</code>.</li>
     * <li>signature - JLS style method signature, required. For example,
     *  <code>(QString;)V</code>.</li>
     * <li>modifiers - optional space separated list of modifiers, for
     *  example, <code>public static</code>.</li>
     * </ol>
	 * @param element the element to check for the method
	 * @param args first arg is method name, secondary args are parameter types signatures
	 * @return true if the method is found in the element, false otherwise
	 */
	private boolean hasMethod(IJavaElement element, Object[] args) {
		try {
			if (args.length > 1) {
	            IType type = getType(element);
				if (type != null && type.exists()) {
					String name = (String) args[0];
					String signature = (String) args[1];
                    String[] parms = Signature.getParameterTypes(signature);
                    String returnType = Signature.getReturnType(signature);
					IMethod candidate = type.getMethod(name, parms);
					if (candidate.exists()) {
                        // check return type
                        if (candidate.getReturnType().equals(returnType)) {
                            // check modifiers
                            if (args.length > 2) {
                                String modifierText = (String) args[2];
                                String[] modifiers = modifierText.split(" "); //$NON-NLS-1$
                                int flags = 0;
                                for (int j = 0; j < modifiers.length; j++) {
                                    String modifier = modifiers[j];
                                    Integer flag = fgModifiers.get(modifier);
                                    if (flag != null) {
                                        flags = flags | flag.intValue();
                                    }
                                }
                                if (candidate.getFlags() == flags) {
                                    return true;
                                }
                            }
                        }
					}
				}
			}
		}
		catch (JavaModelException e) {}
		return false;
	}

	/**
	 * Determines is the java element contains a type with a specific annotation.
     * <p>
     * The syntax for the property tester is of the form: qualified or unqualified annotation name
     * <li>qualified or unqualified annotation name, required. For example,
     *  <code>org.junit.JUnit</code>.</li>
     * </ol>
	 * @param element the element to check for the method
	 * @param annotationType the qualified or unqualified name of the annotation kind to look for
	 * @return true if the type is found in the element, false otherwise
	 */
	private boolean hasTypeWithAnnotation(IJavaElement element, String annotationType) {
		try {
			IType type= getType(element);
			if (type == null || !type.exists()) {
				return false;
			}

			IBuffer buffer= null;
			IOpenable openable= type.getOpenable();
			if (openable instanceof ICompilationUnit) {
				buffer= ((ICompilationUnit) openable).getBuffer();
			} else if (openable instanceof IClassFile) {
				buffer= ((IClassFile) openable).getBuffer();
			}
			if (buffer == null) {
				return false;
			}

			ISourceRange sourceRange= type.getSourceRange();
			ISourceRange nameRange= type.getNameRange();
			if (sourceRange != null && nameRange != null) {
				IScanner scanner= ToolFactory.createScanner(false, false, true, false);
				scanner.setSource(buffer.getCharacters());
				scanner.resetTo(sourceRange.getOffset(), nameRange.getOffset());
				if (findAnnotation(scanner, annotationType)) {
					return true;
				}
			}
		}
		catch (JavaModelException e) {}
		catch (InvalidInputException e) {}
		return false;
	}


	/**
	 * Determines is the java element contains a method with a specific annotation.
     * <p>
     * The syntax for the property tester is of the form: qualified or unqualified annotation name, modifiers
     * <li>qualified or unqualified annotation name, required. For example,
     *  <code>org.junit.JUnit</code>.</li>
     * <li>modifiers - optional space separated list of modifiers, for
     *  example, <code>public static</code>.</li>
     * </ol>
	 * @param element the element to check for the method
	 * @param args the arguments
	 * @return true if the method is found in the element, false otherwise
	 */
	private boolean hasMethodWithAnnotation(IJavaElement element, Object[] args) {
		try {
			String annotationType= (String) args[0];
            int flags = 0;
			if (args.length > 1) {
				String[] modifiers = ((String) args[1]).split(" "); //$NON-NLS-1$
                for (int j = 0; j < modifiers.length; j++) {
                    String modifier = modifiers[j];
                    Integer flag = fgModifiers.get(modifier);
                    if (flag != null) {
                        flags = flags | flag.intValue();
                    }
                }
			} else {
				flags= -1;
			}

			IType type= getType(element);
			if (type == null || !type.exists()) {
				return false;
			}
			IMethod[] methods= type.getMethods();
			if (methods.length == 0) {
				return false;
			}

			IBuffer buffer= null;
			IOpenable openable= type.getOpenable();
			if (openable instanceof ICompilationUnit) {
				buffer= ((ICompilationUnit) openable).getBuffer();
			} else if (openable instanceof IClassFile) {
				buffer= ((IClassFile) openable).getBuffer();
			}
			if (buffer == null) {
				return false;
			}
			IScanner scanner=null; // delay initialization

			for (int i= 0; i < methods.length; i++) {
				IMethod curr= methods[i];
				if (curr.isConstructor() || (flags != -1 && flags != (curr.getFlags() & FLAGS_MASK))) {
					continue;
				}


				ISourceRange sourceRange= curr.getSourceRange();
				ISourceRange nameRange= curr.getNameRange();
				if (sourceRange != null && nameRange != null) {
					if (scanner == null) {
						scanner= ToolFactory.createScanner(false, false, true, false);
						scanner.setSource(buffer.getCharacters());
					}
					scanner.resetTo(sourceRange.getOffset(), nameRange.getOffset());
					if (findAnnotation(scanner, annotationType)) {
						return true;
					}
				}
			}
		} catch (JavaModelException e) {
		} catch (InvalidInputException e) {
		}
		return false;
	}

	private boolean findAnnotation(IScanner scanner, String annotationName) throws InvalidInputException {
		String simpleName= Signature.getSimpleName(annotationName);
		StringBuilder buf= new StringBuilder();
		int tok= scanner.getNextToken();
		while (tok != ITerminalSymbols.TokenNameEOF) {
			if (tok == ITerminalSymbols.TokenNameAT) {
				buf.setLength(0);
				tok= readName(scanner, buf);
				String name= buf.toString();
				if (name.equals(annotationName) || name.equals(simpleName) || name.endsWith('.' + simpleName)) {
					return true;
				}
			} else {
				tok= scanner.getNextToken();
			}
		}
		return false;
	}

	private int readName(IScanner scanner, StringBuilder buf) throws InvalidInputException {
		int tok= scanner.getNextToken();
		while (tok == ITerminalSymbols.TokenNameIdentifier) {
			buf.append(scanner.getCurrentTokenSource());
			tok= scanner.getNextToken();
			if (tok != ITerminalSymbols.TokenNameDOT) {
				return tok;
			}
			buf.append('.');
			tok= scanner.getNextToken();
		}
		return tok;
	}

	/**
     * determines if the project selected has the specified nature
     * @param element the Java element to get the project from
     * @param ntype the specified nature type
     * @return true if the specified nature matches the project, false otherwise
     */
    private boolean hasProjectNature(IJavaElement element, String ntype) {
    	try {
	    	if(element != null) {
	    		IJavaProject jproj = element.getJavaProject();
	    		if(jproj != null) {
	    			IProject proj = jproj.getProject();
	    			return proj.isAccessible() && proj.hasNature(ntype);
	    		}
    		}
	    	return false;
        }
    	catch (CoreException e) {return false;}
    }

	/**
	 * Determines if the element has qname as a parent class
	 * @param element the element to check for the parent class definition
	 * @param qname the fully qualified name of the (potential) parent class
	 * @return true if qname is a parent class, false otherwise
	 */
	private boolean hasSuperclass(IJavaElement element, String qname) {
		try {
			IType type = getType(element);
			if(type != null) {
				IType[] stypes = type.newSupertypeHierarchy(new NullProgressMonitor()).getAllSuperclasses(type);
				for(int i = 0; i < stypes.length; i++) {
					if(stypes[i].getFullyQualifiedName().equals(qname) || stypes[i].getElementName().equals(qname)) {
						return true;
					}
				}
			}
		}
		catch(JavaModelException e) {}
		return false;
	}

	/**
	 * Determines if an item or list of items are found on the build path.
	 * Once any one single items matches though, the method returns true, this method is intended
	 * to be used in OR like situations, where we do not care if all of the items are on the build path, only that one
	 * of them is.
	 *
	 * @param element the element whose build path should be checked
	 * @param args the value(s) to search for on the build path
	 * @return true if any one of the args is found on the build path
	 */
	private boolean hasItemOnBuildPath(IJavaElement element, Object[] args) {
		if(element != null && args != null) {
			IJavaProject project = element.getJavaProject();
			Set<IJavaProject> searched = new HashSet<>();
			searched.add(project);
			return hasItemsOnBuildPath(project, searched, args);
		}
		return false;
	}

	private boolean hasItemsOnBuildPath(IJavaProject project, Set<IJavaProject> searched, Object[] args) {
		try {
			List<IJavaProject> projects = new ArrayList<>();
	        if(project != null && project.exists()) {
	            IClasspathEntry[] entries = project.getResolvedClasspath(true);
	            for(int i = 0; i < entries.length; i++) {
	                IClasspathEntry entry = entries[i];
					IPath path = entry.getPath();
	                String spath = path.toPortableString();
	                for(int j = 0; j < args.length; j++) {
	                	if(spath.lastIndexOf((String)args[j]) != -1) {
	                		return true;
	                	}
	                }
	                if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
	                	String name = entry.getPath().lastSegment();
	                	IProject dep = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
	                	IJavaProject javaProject = JavaCore.create(dep);
	                	if (!searched.contains(javaProject)) {
	                		projects.add(javaProject);
	                	}
	                }
	            }
	        }
	        // search referenced projects
	        Iterator<IJavaProject> iterator = projects.iterator();
	        while (iterator.hasNext()) {
	        	IJavaProject jp = iterator.next();
	        	searched.add(jp);
	        	if (hasItemsOnBuildPath(jp, searched, args)) {
	        		return true;
	        	}
	        }
		} catch (JavaModelException e) {}
		return false;
	}

	/**
	 * determines if the element implements a given interface
	 * @param element the element to check for the interface
	 * @param qname the fully qualified name of the interface to check for
	 * @return true if the element does implement the interface, false otherwise
	 */
	private boolean implementsInterface(IJavaElement element, String qname) {
		try {
			IType type = getType(element);
			if(type != null) {
				IType[] itypes = type.newSupertypeHierarchy(new NullProgressMonitor()).getAllInterfaces();
				for(int i = 0; i < itypes.length; i++) {
					if(itypes[i].getFullyQualifiedName().equals(qname)) {
						return true;
					}
				}
			}
		}
		catch(JavaModelException e) {}
		return false;
	}

	/**
	 * Method runs the tests defined from extension points for Run As... and Debug As... menu items.
	 * Currently this test optimistically considers everything not a source file. In this context we
	 * consider an optimistic approach to mean that the test will always return true.
	 *
	 * There are many reasons for the optimistic choice some of them are outlined below.
	 * <ul>
	 * <li>Performance (in terms of time needed to display menu) cannot be preserved. To know what to allow
	 * in any one of the menus we would have to search all of the children of the container to determine what it contains
	 * and what can be launched by what.</li>
	 * <li>If inspection of children of containers were done, a user might want to choose a different launch type, even though our tests
	 * filter it out.</li>
	 * </ul>
	 * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
	 * @since 3.2
	 * @return true if the specified tests pass, or the context is a container, false otherwise
	 */
	@Override
	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
		if (PROPERTY_IS_CONTAINER.equals(property)) {
			if (receiver instanceof IAdaptable) {
				IResource resource = ((IAdaptable) receiver).getAdapter(IResource.class);
				if (resource != null) {
					return resource instanceof IContainer;
				}
			}
			return false;
		}
		IJavaElement element = null;
		if (receiver instanceof IAdaptable) {
			element = ((IAdaptable) receiver).getAdapter(IJavaElement.class);
			if(element != null) {
				if(!element.exists()) {
					return false;
				}
			}
		}
		if(PROPERTY_HAS_MAIN.equals(property)) {
			return hasMain(element);
		}
		if (PROPERTY_HAS_METHOD.equals(property)) {
			return hasMethod(element, args);
		}
		if (PROPERTY_HAS_METHOD_WITH_ANNOTATION.equals(property)) {
			return hasMethodWithAnnotation(element, args);
		}
		if (PROPERTY_HAS_TYPE_WITH_ANNOTATION.equals(property)) {
			return hasTypeWithAnnotation(element, (String)args[0]);
		}
		if(PROPERTY_BUILDPATH_REFERENCE.equals(property)) {
			return hasItemOnBuildPath(element, args);
		}
		if(PROPERTY_EXTENDS_CLASS.equals(property)) {
			return hasSuperclass(element, (String)args[0]);
		}
		if(PROPERTY_PROJECT_NATURE.equals(property)) {
			return hasProjectNature(element, (String)args[0]);
		}
		if(PROPERTY_EXTENDS_INTERFACE.equals(property)) {
			return implementsInterface(element, (String)args[0]);
		}
		if (PROPERTY_IS_PACKAGE_FRAGMENT.equals(property)) {
			return element instanceof IPackageFragment;
		}
		if (PROPERTY_IS_PACKAGE_FRAGMENT_ROOT.equals(property)) {
			return element instanceof IPackageFragmentRoot;
		}
		return false;
	}

}
