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

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Properties;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.netbeans.api.java.classpath.ClassPath;
import static org.netbeans.api.java.classpath.ClassPath.COMPILE;
import org.netbeans.api.java.project.classpath.ProjectClassPathModifier;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import static org.netbeans.modules.java.testrunner.JavaUtils.PROP_JUNIT_SELECTED_VERSION;
import org.netbeans.modules.junit.api.JUnitUtils;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.netbeans.spi.project.LookupProvider;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
import org.netbeans.spi.project.ui.ProjectProblemResolver;
import org.netbeans.spi.project.ui.ProjectProblemsProvider;
import org.netbeans.spi.project.ui.ProjectProblemsProvider.ProjectProblem;
import org.netbeans.spi.project.ui.ProjectProblemsProvider.Result;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.Lookups;

/**
 *
 * @author Theofanis Oikonomou
 */
@LookupProvider.Registration(projectType = {
    "org-netbeans-modules-j2ee-clientproject",
    "org-netbeans-modules-j2ee-ejbjarproject",
    "org-netbeans-modules-java-j2seproject",
    "org-netbeans-modules-web-project"
})
public class JUnitProjectOpenedHook implements LookupProvider {

    //full name of a file specific for the JUnit 3.8.x library
    private static final String JUNIT3_SPECIFIC = "junit/awtui/TestRunner.class"; //NOI18N
    // full name of a file specific for the JUnit 4.x library
    private static final String JUNIT4_SPECIFIC = "org/junit/Test.class"; //NOI18N
    // full name of a file specific for the Hamcrest library
    private static final String HAMCREST_SPECIFIC = "org/hamcrest/Matcher.class"; //NOI18N
    //constant for action.getValue() holding the text to show to users..
    public static final String ACT_START_MESSAGE = "START_MESSAGE";
    private static final String MISSING_JUNIT_BINARIES = "MISSINGJUNITBINARIES"; //NOI18N
    private static final String PROP_JAVAC_TEST_CLASSPATH = "javac.test.classpath"; //NOI18N
    private static final RequestProcessor RP = new RequestProcessor(JUnitProjectProblemsProvider.class);
    private final WeakHashMap<Project, WeakReference<JUnitProjectProblemsProvider>> map = new WeakHashMap<Project, WeakReference<JUnitProjectProblemsProvider>>();

    @NbBundle.Messages({"Error_display_name_junit=JUnit 3.8.2 binaries missing.",
        "Error_description_junit=Beginning with Netbeans 8.1, JUnit 3.8.2 binaries were removed.\n\n"
        + "Click the resolve button to automatically update the test dependency to JUnit 4.x library definition. "
        + "JUnit 4.x has a compatibility mode in order to handle JUnit 3.x testcases.\n\n"
        + "Alternatively download junit-3.8.2.jar and add it manually as your project's test dependency.",
        "Error_display_name_junit4=Hamcrest binaries missing",
        "Error_description_junit4=JUnit 4.12 does not bundle hamcrest matchers library.\n\n"
        + "Click the resolve button to automatically add hamcrest as your project's test dependency."})
    @Override
    public Lookup createAdditionalLookup(final Lookup lookup) {

        final Project p = lookup.lookup(Project.class);
        map.put(p, new WeakReference<JUnitProjectProblemsProvider>(new JUnitProjectProblemsProvider()));

        ProjectOpenedHook projectOpenedHook = new ProjectOpenedHook() {
            @Override
            protected void projectOpened() {
                final ClassPath classPath = getTestClassPath(p);
                if (classPath != null) {
                    if (classPath.findResource(JUNIT3_SPECIFIC) != null || 
                            classPath.toString().contains("${libs.junit.classpath}")) {
                        getJUnitProjectProblemsProvider(p).setProblem(ProjectProblem.createError(
                            Bundle.Error_display_name_junit(), Bundle.Error_description_junit(),
                            new JUnitProblemResolver(new UpdateToJUnit4Action(p, true), MISSING_JUNIT_BINARIES)));
                    }
                    if (classPath.findResource(JUNIT4_SPECIFIC) != null && classPath.findResource(HAMCREST_SPECIFIC) == null) {
                        getJUnitProjectProblemsProvider(p).setProblem(ProjectProblem.createError(
                            Bundle.Error_display_name_junit4(), Bundle.Error_description_junit4(),
                            new JUnitProblemResolver(new UpdateToJUnit4Action(p, false), MISSING_JUNIT_BINARIES)));
                    }
                }
            }

            @Override
            protected void projectClosed() {
                getJUnitProjectProblemsProvider(p).setProblem(null);
            }
        };
        return Lookups.fixed(projectOpenedHook, getJUnitProjectProblemsProvider(p));
    }
    
    private JUnitProjectProblemsProvider getJUnitProjectProblemsProvider(Project p) {
        WeakReference<JUnitProjectProblemsProvider> problemsProviderRef = map.get(p);
        if(problemsProviderRef == null || problemsProviderRef.get() == null) {
            problemsProviderRef = new WeakReference<JUnitProjectProblemsProvider>(new JUnitProjectProblemsProvider());
            map.put(p, problemsProviderRef);
        }
        return problemsProviderRef.get();
    }

    /**
     * Finds classpath used for compilation of tests.
     *
     * @param project project whose classpath should be found
     * @return test classpath of the given project, or {@literal null} if it
     * could not be determined
     * @throws java.lang.IllegalStateException if no test folders were found in
     * the project
     */
    private static ClassPath getTestClassPath(final Project project) throws IllegalStateException {
        assert project != null;

        final Collection<FileObject> testFolders = JUnitUtils.getTestFolders(project);

        final ClassPathProvider cpProvider = project.getLookup().lookup(ClassPathProvider.class);
        if (cpProvider == null) {
            return null;
        }

        for (FileObject testRoot : testFolders) {
            ClassPath testClassPath = cpProvider.findClassPath(testRoot, COMPILE);
            if (testClassPath != null) {
                return testClassPath;
            }
        }
        return null;
    }

    private class JUnitProjectProblemsProvider implements ProjectProblemsProvider {

        private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
        private ProjectProblemsProvider.ProjectProblem pp;

        public JUnitProjectProblemsProvider() {
        }

        synchronized void setProblem(ProjectProblemsProvider.ProjectProblem pp) {
            this.pp = pp;
            if (pp == null && this.pp == null) {
                return; //ignore this case, dont' fire change..
            }
            pcs.firePropertyChange(ProjectProblemsProvider.PROP_PROBLEMS, null, null);
        }

        @Override
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            pcs.addPropertyChangeListener(listener);
        }

        @Override
        public void removePropertyChangeListener(PropertyChangeListener listener) {
            pcs.removePropertyChangeListener(listener);
        }

        @Override
        public synchronized Collection<? extends ProjectProblemsProvider.ProjectProblem> getProblems() {
            if (pp != null) {
                return Collections.singleton(pp);
            } else {
                return Collections.emptyList();
            }
        }
    }

    private class JUnitProblemResolver implements ProjectProblemResolver {

        private final Action action;
        private final String id;

        public JUnitProblemResolver(Action correctiveAction, String id) {
            this.action = correctiveAction;
            this.id = id;
        }
        
        @Override
        public java.util.concurrent.Future<ProjectProblemsProvider.Result> resolve() {
            ProjectProblemsProvider.Result res;
            if (action != null) {
                action.actionPerformed(null);
                String text = (String) action.getValue(ACT_START_MESSAGE);
                if (text != null) {
                    res = ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.RESOLVED, text);
                } else {
                    res = ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.RESOLVED);
                }
            } else {
                res = ProjectProblemsProvider.Result.create(ProjectProblemsProvider.Status.UNRESOLVED, "No resolution for the problem");
            }
            RunnableFuture<ProjectProblemsProvider.Result> f = new FutureTask<>(new Runnable() {
                @Override
                public void run() {
                }
            }, res);
            f.run();
            return f;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 11 * hash + (this.id != null ? this.id.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final JUnitProblemResolver other = (JUnitProblemResolver) obj;
            return !((this.id == null) ? (other.id != null) : !this.id.equals(other.id));
        }
    }

    private class UpdateToJUnit4Action extends AbstractAction {

        private final Project p;
        private final boolean isJUnit3specific;

        @NbBundle.Messages({"Action_display_name_junit=Update to JUnit 4.x",
            "Action_start_msg_junit=Test dependency was updated to JUnit 4.x library.",
            "Action_display_name_junit4=Add Hamcrest library",
            "Action_start_msg_junit4=Hamcrest library was added as test dependency."})
        UpdateToJUnit4Action(Project project, boolean isJUnit3specific) {
            putValue(Action.NAME, isJUnit3specific ? Bundle.Action_display_name_junit() : Bundle.Action_display_name_junit4());
            putValue(ACT_START_MESSAGE, isJUnit3specific ? Bundle.Action_start_msg_junit(): Bundle.Action_start_msg_junit4());
            p = project;
            this.isJUnit3specific = isJUnit3specific;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            FileObject buildXML = p.getProjectDirectory().getFileObject("build.xml"); //NOI18N
            Library junit4lib = LibraryManager.getDefault().getLibrary("junit_4"); //NOI18N
            Library hamcrestlib = LibraryManager.getDefault().getLibrary("hamcrest"); //NOI18N
            if (buildXML != null) {
                try {
                    updateProjectProperties(p);
                    Collection<FileObject> testFolders = JUnitUtils.getTestFolders(p);
                    ProjectClassPathModifier.addLibraries(new Library[]{junit4lib, hamcrestlib}, testFolders.toArray(new FileObject[testFolders.size()])[0], ClassPath.COMPILE);
                    getJUnitProjectProblemsProvider(p).setProblem(null);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                } catch (UnsupportedOperationException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }

        private void updateProjectProperties(Project project) throws IOException {
            final FileObject projectDir = project.getProjectDirectory();
            ProjectManager.mutex().postWriteRequest(new Runnable() {
                @Override
                public void run() {
                    try {
                        FileObject projectProperties = FileUtil.createData(projectDir, AntProjectHelper.PROJECT_PROPERTIES_PATH);
                        Properties props = getProjectProperties(projectDir);

                        if (isJUnit3specific) {
                            String testClasspath = props.getProperty(PROP_JAVAC_TEST_CLASSPATH);
                            props.put(PROP_JAVAC_TEST_CLASSPATH, testClasspath.replace("${libs.junit.classpath}", ""));
                        }
                        props.put(PROP_JUNIT_SELECTED_VERSION, isJUnit3specific ? "3" : "4");
                        OutputStream propertiesOS = projectProperties.getOutputStream();
                        props.store(propertiesOS, null);
                        propertiesOS.close();
                    } catch (IOException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            });
        }

        private Properties getProjectProperties(FileObject projectDir) throws IOException {
            FileObject projectProperties = FileUtil.createData(projectDir, AntProjectHelper.PROJECT_PROPERTIES_PATH);
            InputStream propertiesIS = projectProperties.getInputStream();
            Properties props = new Properties();
            props.load(propertiesIS);
            propertiesIS.close();
            return props;
        }
    }
}
