/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.java.testrunner;

import java.net.URL;
import java.util.*;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.modules.gsf.testrunner.plugin.CommonPlugin.CreateTestParam;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;

/**
 *
 * @author  rmatous
 * @author  Marian Petras
 * @version 1.1
 */
public class CommonTestUtil {
    static private final String JAVA_SOURCES_SUFFIX = "java"; //NOI18N

    /**
     */
    public static boolean isJavaFile(FileObject fileObj) {
        return "java".equals(fileObj.getExt())                          //NOI18N
               || "text/x-java".equals(FileUtil.getMIMEType(fileObj));  //NOI18N
    }
    
    /**
     * Finds all <code>SourceGroup</code>s of the given project
     * containing a class of the given name.
     *
     * @param  project  project to be searched for matching classes
     * @param  className  class name pattern
     * @return  unmodifiable collection of <code>SourceGroup</code>s
     *          which contain files corresponding to the given name
     *          (may be empty but not <code>null</code>)
     * @author  Marian Petras
     */
    public static Collection<SourceGroup> findSourceGroupOwners(
            final Project project,
            final String className) {
        final SourceGroup[] sourceGroups
                = new JavaUtils(project).getJavaSourceGroups();
        if (sourceGroups.length == 0) {
            return Collections.<SourceGroup>emptyList();
        }
        
        final String relativePath = className.replace('.', '/')
                                    + ".java";                          //NOI18N
        
        ArrayList<SourceGroup> result = new ArrayList<SourceGroup>(4);
        for (int i = 0; i < sourceGroups.length; i++) {
            SourceGroup srcGroup = sourceGroups[i];
            FileObject root = srcGroup.getRootFolder();
            FileObject file = root.getFileObject(relativePath);
            if (file != null && FileUtil.isParentOf(root, file)
                             && srcGroup.contains(file)) {
                result.add(srcGroup);
            }
        }
        if (result.isEmpty()) {
            return Collections.<SourceGroup>emptyList();
        }
        result.trimToSize();
        return Collections.unmodifiableList(result);
    }

    /**
     * Finds <code>SourceGroup</code>s where a test for the given class
     * can be created (so that it can be found by the projects infrastructure
     * when a test for the class is to be opened or run).
     *
     * @param  fileObject  <code>FileObject</code> to find target
     *                     <code>SourceGroup</code>(s) for
     * @return  an array of objects - each of them can be either
     *          a <code>SourceGroup</code> for a possible target folder
     *          or simply a <code>FileObject</code> representing a possible
     *          target folder (if <code>SourceGroup</code>) for the folder
     *          was not found);
     *          the returned array may be empty but not <code>null</code>
     * @author  Marian Petras
     */
    public static Object[] getTestTargets(FileObject fileObject) {
        
        /* .) get project owning the given FileObject: */
        final Project project = FileOwnerQuery.getOwner(fileObject);
        if (project == null) {
            return new Object[0];
        }
        
        SourceGroup sourceGroupOwner = findSourceGroupOwner(fileObject);
        if (sourceGroupOwner == null) {
            return new Object[0];
        }
        
        /* .) get URLs of target SourceGroup's roots: */
        final URL[] rootURLs = UnitTestForSourceQuery.findUnitTests(sourceGroupOwner.getRootFolder());
        if (rootURLs.length == 0) {
            return new Object[0];
        }
        
        /* .) convert the URLs to FileObjects: */
        boolean someSkipped = false;
        FileObject[] sourceRoots = new FileObject[rootURLs.length];
        for (int i = 0; i < rootURLs.length; i++) {
            if ((sourceRoots[i] = URLMapper.findFileObject(rootURLs[i]))
                    == null) {
                ErrorManager.getDefault().log(
                        ErrorManager.INFORMATIONAL,
                           "No FileObject found for the following URL: "//NOI18N
                           + rootURLs[i]);
                someSkipped = true;
                continue;
            }
            if (FileOwnerQuery.getOwner(sourceRoots[i]) != project) {
                ErrorManager.getDefault().notify(
                        ErrorManager.INFORMATIONAL,
                        new IllegalStateException(
                    "Source root found by FileOwnerQuery points "       //NOI18N
                    + "to a different project for the following URL: "  //NOI18N
                    + rootURLs[i]));
                sourceRoots[i] = null;
                someSkipped = true;
                continue;
            }
        }
        
        if (someSkipped) {
            FileObject roots[] = skipNulls(sourceRoots, new FileObject[0]);
            if (roots.length == 0) {
                return new Object[0];
            }
            sourceRoots = roots;
        }
        
        /* .) find SourceGroups corresponding to the FileObjects: */
        final Object[] targets = new Object[sourceRoots.length];
        Map<FileObject,SourceGroup> map = getFileObject2SourceGroupMap(project);
        for (int i = 0; i < sourceRoots.length; i++) {
            SourceGroup srcGroup = map.get(sourceRoots[i]);
            targets[i] = srcGroup != null ? srcGroup : sourceRoots[i];
        }
        return targets;
    }
    
    /**
     * Finds a <code>SourceGroup</code> the given file belongs to.
     * Only Java <code>SourceGroup</code>s are taken into account.
     *
     * @param  file  <code>FileObject</code> whose owning
     *               <code>SourceGroup</code> to be found
     * @return  Java <code>SourceGroup</code> containing the given
     *          file; or <code>null</code> if no such
     *          <code>SourceGroup</code> was found
     * @author  Marian Petras
     */
    public static SourceGroup findSourceGroupOwner(FileObject file) {
        final Project project = FileOwnerQuery.getOwner(file);
        return project == null ? null : findSourceGroupOwner(project, file);
    }
    
    /**
     * Finds a <code>SourceGroup</code> the given file belongs to.
     * Only Java <code>SourceGroup</code>s are taken into account. 
     *
     * @param project the <code>Project</code> the file belongs to
     * @param  file  <code>FileObject</code> whose owning
     *               <code>SourceGroup</code> to be found
     * @return  Java <code>SourceGroup</code> containing the given
     *          file; or <code>null</code> if no such
     *          <code>SourceGroup</code> was found
     */

    public static SourceGroup findSourceGroupOwner(Project project, FileObject file) {        
        final SourceGroup[] sourceGroups
                = new JavaUtils(project).getJavaSourceGroups();
        for (int i = 0; i < sourceGroups.length; i++) {
            SourceGroup srcGroup = sourceGroups[i];
            FileObject root = srcGroup.getRootFolder();
            if (((file==root)||(FileUtil.isParentOf(root,file))) && 
                 srcGroup.contains(file)) {
                return srcGroup;
            }
        }
        return null;
    }
    
    /**
     * Creates a copy of the given array, except that <code>null</code> objects
     * are omitted.
     * The length of the returned array is (<var>l</var> - <var>n</var>), where
     * <var>l</var> is length of the passed array and <var>n</var> is number
     * of <code>null</code> elements of the array. Order of
     * non-<code>null</code> elements is kept in the returned array.
     * The returned array is always a new array, even if the passed
     * array does not contain any <code>null</code> elements.
     *
     * @param  objs  array to copy
     * @param  type  an empty array of the correct type to be returned
     * @return  array containing the same objects as the passed array, in the
     *          same order, just with <code>null</code> elements missing
     * @author  Marian Petras
     */
    public static <T> T[] skipNulls(final T[] objs, final T[] type) {
        List<T> resultList = new ArrayList<T>(objs.length);
        
        for (int i = 0; i < objs.length; i++) {
            if (objs[i] != null) {
                resultList.add(objs[i]);
            }
        }
        
        return resultList.toArray(type);
    }
    
    /**
     * Creates a map from folders to <code>SourceGroup</code>s of a given
     * project.
     * The map allows to ascertian for a given folder
     * which <code>SourceGroup</code> it is a root folder of.
     *
     * @param  project  project whose <code>SourceGroup</code>s should be in the
     *                  returned map
     * @return  map from containing all <code>SourceGroup</code>s of a given
     *          project, having their root folders as keys
     * @author  Marian Petras
     */
    public static Map<FileObject,SourceGroup> getFileObject2SourceGroupMap(
                                                              Project project) {
        final SourceGroup[] sourceGroups
                = new JavaUtils(project).getJavaSourceGroups();
        
        if (sourceGroups.length == 0) {
            return Collections.<FileObject,SourceGroup>emptyMap();
        } else if (sourceGroups.length == 1) {
            return Collections.singletonMap(sourceGroups[0].getRootFolder(),
                                            sourceGroups[0]);
        } else {
            Map<FileObject,SourceGroup> map;
            map = new HashMap<FileObject,SourceGroup>(
                    Math.round(sourceGroups.length * 1.4f + .5f),
                               .75f);
            for (int i = 0; i < sourceGroups.length; i++) {
                map.put(sourceGroups[i].getRootFolder(),
                        sourceGroups[i]);
            }
            return map;
        }
    }

    /**
     * Creates a map of parameters according to the current JUnit module
     * settings.<br />
     * Note: The map may not contain all the necessary settings,
     *       i.g. name of a test class is missing.
     *
     * @param  multipleFiles  if {@literal true}, the map should contain
     *                        also settings need for creation of multiple
     *                        tests
     * @return  map of settings to be used by a
     *          {@link org.netbeans.modules.junit.plugin JUnitPlugin}
     * @see  org.netbeans.modules.junit.plugin.JUnitPlugin
     */
    public static Map<CreateTestParam, Object> getSettingsMap(
            boolean multipleFiles) {
        final CommonSettings settings = CommonSettings.getDefault();
        final Map<CreateTestParam, Object> params
                    = new HashMap<CreateTestParam, Object>(17);
        
        params.put(CreateTestParam.INC_PUBLIC,
                   Boolean.valueOf(settings.isMembersPublic()));
        params.put(CreateTestParam.INC_PROTECTED,
                   Boolean.valueOf(settings.isMembersProtected()));
        params.put(CreateTestParam.INC_PKG_PRIVATE,
                   Boolean.valueOf(settings.isMembersPackage()));
        params.put(CreateTestParam.INC_CODE_HINT,
                   Boolean.valueOf(settings.isBodyComments()));
        params.put(CreateTestParam.INC_METHOD_BODIES,
                   Boolean.valueOf(settings.isBodyContent()));
        params.put(CreateTestParam.INC_JAVADOC,
                   Boolean.valueOf(settings.isJavaDoc()));
        
        if (multipleFiles) {
            params.put(CreateTestParam.INC_GENERATE_SUITE,
                       Boolean.valueOf(settings.isGenerateSuiteClasses()));
            params.put(CreateTestParam.INC_PKG_PRIVATE_CLASS,
                    Boolean.valueOf(settings.isIncludePackagePrivateClasses()));
            params.put(CreateTestParam.INC_ABSTRACT_CLASS,
                       Boolean.valueOf(settings.isGenerateAbstractImpl()));
            params.put(CreateTestParam.INC_EXCEPTION_CLASS,
                       Boolean.valueOf(settings.isGenerateExceptionClasses()));
        }
        else {
            // If a class is explicitly selected then corresponding test class
            // should be generated in any cases.
            params.put(CreateTestParam.INC_PKG_PRIVATE_CLASS,
                       Boolean.valueOf(true));
            params.put(CreateTestParam.INC_ABSTRACT_CLASS,
                       Boolean.valueOf(true));
            params.put(CreateTestParam.INC_EXCEPTION_CLASS,
                       Boolean.valueOf(true));
        }
        
        params.put(CreateTestParam.INC_SETUP,
                   Boolean.valueOf(settings.isGenerateSetUp()));
        params.put(CreateTestParam.INC_TEAR_DOWN,
                   Boolean.valueOf(settings.isGenerateTearDown()));
        params.put(CreateTestParam.INC_CLASS_SETUP,
                   Boolean.valueOf(settings.isGenerateClassSetUp()));
        params.put(CreateTestParam.INC_CLASS_TEAR_DOWN,
                   Boolean.valueOf(settings.isGenerateClassTearDown()));
        
        return params;
    }
    
}
