/*
 * 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.junit.ui;

import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.modules.gsf.testrunner.api.TestCreatorProvider;
import static org.netbeans.modules.gsf.testrunner.api.TestCreatorProvider.getSourceGroup;
import org.netbeans.modules.gsf.testrunner.plugin.CommonPlugin;
import org.netbeans.modules.gsf.testrunner.ui.api.UICommonUtils;
import org.netbeans.modules.junit.api.JUnitVersion;
import org.netbeans.modules.junit.api.JUnitTestUtil;
import org.netbeans.modules.junit.plugin.JUnitPlugin;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

abstract class AbstractJUnitTestCreatorProvider extends TestCreatorProvider {
    abstract JUnitVersion useVersion();

    @Override
    public boolean enable(FileObject[] activatedFOs) {
        if (activatedFOs == null || activatedFOs.length == 0) {
            return false;
        }
        /*
         * In most cases, there is just one node selected - that is why
         * this case is handled in a special, more effective way
         * (no collections and iterators created).
         */
        if (activatedFOs.length == 1) {
            FileObject fileObj = activatedFOs[0];

            Project project;
            if ((fileObj != null)
                && fileObj.isValid()
                // selected FO might be folder or java file
                && (fileObj.isFolder() || JUnitTestUtil.isJavaFile(fileObj))
                && ((project = FileOwnerQuery.getOwner(fileObj)) != null)
                && (getSourceGroup(fileObj, project) != null)) {

                JUnitPlugin plugin = JUnitTestUtil.getPluginForProject(project, useVersion());
                return JUnitTestUtil.canCreateTests(plugin, fileObj);
            } else {
                return false;
            }
        }

        final Collection<FileObject> fileObjs = new ArrayList<>(activatedFOs.length);
        Project theProject = null;
        boolean result = false;
        for (FileObject fileObj : activatedFOs) {
            if ((fileObj == null) || !fileObj.isValid()
                // selected FO might be folder or java file
                && (fileObj.isFolder() || JUnitTestUtil.isJavaFile(fileObj))) {
                continue;
            }

            fileObjs.add(fileObj);

            Project prj = FileOwnerQuery.getOwner(fileObj);
            if (prj != null) {
                if (theProject == null) {
                    theProject = prj;
                }
                if (prj != theProject) {
                    return false;        /* files from different projects */

                }

                if (getSourceGroup(fileObj, prj) != null) {
                    result = true;
                }
            }
        }

        if (theProject != null) {
            JUnitPlugin plugin = JUnitTestUtil.getPluginForProject(theProject);
            result &= JUnitTestUtil.canCreateTests(
                            plugin,
                            fileObjs.toArray(new FileObject[fileObjs.size()]));
        }

        return result;
    }

    @Override
    public void createTests(Context context) {
        String problem;
        if ((problem = checkNodesValidity(context.getActivatedFOs())) != null) {
            // TODO report problem
            NotifyDescriptor msg = new NotifyDescriptor.Message(
                    problem, NotifyDescriptor.WARNING_MESSAGE);
            DialogDisplayer.getDefault().notify(msg);
            return;
        }

        final FileObject[] filesToTest = context.getActivatedFOs();
        if (filesToTest == null) {
            return;     //XXX: display some message
        }

        /*
         * Determine the plugin to be used:
         */
        final JUnitPlugin plugin = JUnitTestUtil.getPluginForProject(
            FileOwnerQuery.getOwner(filesToTest[0]), useVersion()
        );

        if (!JUnitTestUtil.createTestActionCalled(
                plugin, filesToTest)) {
            return;
        }

        /*
         * Store the configuration data:
         */
        final boolean singleClass = context.isSingleClass();
        final Map<CommonPlugin.CreateTestParam, Object> params = JUnitTestUtil.getSettingsMap(!singleClass);
        if (singleClass) {
            params.put(CommonPlugin.CreateTestParam.CLASS_NAME, context.getTestClassName());
        }
        final FileObject targetFolder = context.getTargetFolder();
        if(context.isIntegrationTests()) {
            params.put(CommonPlugin.CreateTestParam.INC_GENERATE_INTEGRATION_TEST, Boolean.TRUE);
        } else {
            params.put(CommonPlugin.CreateTestParam.INC_GENERATE_INTEGRATION_TEST, Boolean.FALSE);
        }

        RequestProcessor.getDefault().post(new Runnable() {

            @Override
            public void run() {
                /*
                 * Now create the tests:
                 */
                final FileObject[] testFileObjects = JUnitTestUtil.createTests(
                        plugin,
                        filesToTest,
                        targetFolder,
                        params);

                /*
                 * Open the created/updated test class if appropriate:
                 */
                if (testFileObjects.length == 1) {
                    try {
                        DataObject dobj = DataObject.find(testFileObjects[0]);
                        final EditorCookie ec = dobj.getLookup().lookup(EditorCookie.class);
                        if (ec != null) {
                            EventQueue.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    ec.open();
                                }
                            });
                        }
                    } catch (DataObjectNotFoundException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * Checks that the selection of nodes the dialog is invoked on is valid.
     * @return String message describing the problem found or null, if the
     *         selection is ok
     */
    private static String checkNodesValidity(FileObject[] files) {

        Project project = getProject(files);
        if (project == null) {
            return NbBundle.getMessage(JUnitTestCreatorProvider.class,
                                       "MSG_multiproject_selection");   //NOI18N
        }

        if (!checkPackages(files)) {
            return NbBundle.getMessage(JUnitTestCreatorProvider.class,
                                       "MSG_invalid_packages");         //NOI18N
        }

        return null;
    }

    /**
     * Extracts {@code FileObject}s from the given nodes.
     * Nodes that have (direct or indirect) parent nodes among the given
     * nodes are ignored.
     *
     * @return  a non-empty array of {@code FileObject}s
     *          represented by the given nodes;
     *          or {@code null} if no {@code FileObject} was found;
     */
    private static FileObject[] getFileObjectsFromNodes(final Node[] nodes){
        FileObject[] fileObjects = new FileObject[nodes.length];
        List<FileObject> fileObjectsList = null;

        for (int i = 0; i < nodes.length; i++) {
            final Node node = nodes[i];
            final FileObject fo;
            if (!hasParentAmongNodes(nodes, i)
                    && ((fo = getTestFileObject(node)) != null)) {
                if (fileObjects != null) {
                    fileObjects[i] = fo;
                } else {
                    if (fileObjectsList == null) {
                        fileObjectsList = new ArrayList<FileObject>(
                                                        nodes.length - i);
                    }
                    fileObjectsList.add(fo);
                }
            } else {
                fileObjects = null;     //signs that some FOs were skipped
            }
        }
        if (fileObjects == null) {
            if (fileObjectsList != null) {
                fileObjects = fileObjectsList.toArray(
                        new FileObject[fileObjectsList.size()]);
                fileObjectsList = null;
            }
        }

        return fileObjects;
    }

    /**
     * Check that all the files (folders or java files) have correct java
     * package names.
     * @return true if all are fine
     */
    private static boolean checkPackages(FileObject[] files) {
        if (files.length == 0) {
            return true;
        } else {
            Project project = FileOwnerQuery.getOwner(files[0]);
            for (int i = 0 ; i < files.length; i++) {
                String packageName = getPackage(project, files[i]);
                if ((packageName == null)
                        || !JUnitTestUtil.isValidPackageName(packageName)) {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * Get the package name of <code>file</code>.
     *
     * @param project owner of the file (for performance reasons)
     * @param file the FileObject whose packagename to get
     * @return package name of the file or null if it cannot be retrieved
     */
    private static String getPackage(Project project, FileObject file) {
        SourceGroup srcGrp = JUnitTestUtil.findSourceGroupOwner(project, file);
        if (srcGrp!= null) {
            ClassPath cp = ClassPathSupport.createClassPath(
                    new FileObject [] {srcGrp.getRootFolder()});
            return cp.getResourceName(file, '.', false);
        } else {
            return null;
        }
    }


    private static FileObject[] getFiles(Node[] nodes) {
        FileObject[] ret = new FileObject[nodes.length];
        for (int i = 0 ; i < nodes.length ; i++) {
            ret[i]  = UICommonUtils.getFileObjectFromNode(nodes[i]);
        }
        return ret;
    }

    /**
     * Get the single project for <code>nodes</code> if there is such.
     * If the nodes belong to different projects or some of the nodes doesn't
     * have a project, return null.
     */
    private static Project getProject(FileObject[] files) {
        Project project = null;
        for (int i = 0 ; i < files.length; i++) {
            Project nodeProject = FileOwnerQuery.getOwner(files[i]);
            if (project == null) {
                project = nodeProject;
            } else if (project != nodeProject) {
                return null;
            }
        }
        return project;
    }

    /**
     * Grabs and checks a <code>FileObject</code> from the given node.
     * If either the file could not be grabbed or the file does not pertain
     * to any project, a message is displayed.
     *
     * @param  node  node to get a <code>FileObject</code> from.
     * @return  the grabbed <code>FileObject</code>,
     *          or <code>null</code> in case of failure
     */
    private static FileObject getTestFileObject(final Node node) {
        final FileObject fo = UICommonUtils.getFileObjectFromNode(node);
        if (fo == null) {
            JUnitTestUtil.notifyUser(NbBundle.getMessage(
                    JUnitTestCreatorProvider.class,
                    "MSG_file_from_node_failed"));                      //NOI18N
            return null;
        }
        ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
        if (cp == null) {
            JUnitTestUtil.notifyUser(NbBundle.getMessage(
                    JUnitTestCreatorProvider.class,
                    "MSG_no_project",                                   //NOI18N
                    fo));
            return null;
        }
        return fo;
    }

    private static boolean hasParentAmongNodes(final Node[] nodes,
                                               final int idx) {
        Node node;

        node = nodes[idx].getParentNode();
        while (null != node) {
            for (int i = 0; i < nodes.length; i++) {
                if (i == idx) {
                    continue;
                }
                if (node == nodes[i]) {
                    return true;
                }
            }
            node = node.getParentNode();
        }
        return false;
    }


}
