/*******************************************************************************
 * 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",       Integer.valueOf(Flags.AccPublic)); //$NON-NLS-1$
        fgModifiers.put("protected",    Integer.valueOf(Flags.AccProtected)); //$NON-NLS-1$
        fgModifiers.put("private",      Integer.valueOf(Flags.AccPrivate)); //$NON-NLS-1$
        fgModifiers.put("static",       Integer.valueOf(Flags.AccStatic)); //$NON-NLS-1$
        fgModifiers.put("final",        Integer.valueOf(Flags.AccFinal)); //$NON-NLS-1$
        fgModifiers.put("synchronized", Integer.valueOf(Flags.AccSynchronized)); //$NON-NLS-1$
        fgModifiers.put("abstract",     Integer.valueOf(Flags.AccAbstract)); //$NON-NLS-1$
        fgModifiers.put("native",       Integer.valueOf(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;
	}

}
