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

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import org.apache.maven.model.Model;
import org.apache.maven.model.ModelBase;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Profile;
import org.apache.maven.model.io.ModelReader;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.modules.maven.api.FileUtilities;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.api.classpath.ProjectSourcesClassPathProvider;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.indexer.api.RepositoryIndexer;
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.netbeans.modules.maven.options.MavenSettings;
import org.netbeans.modules.maven.problems.BatchProblemNotifier;
import org.netbeans.modules.maven.queries.MavenFileOwnerQueryImpl;
import org.netbeans.spi.project.ProjectServiceProvider;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.modules.Places;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;

/**
 * openhook implementation, register global classpath and also
 * register the project in the fileOwnerQuery impl, that's important for interproject
 * dependencies to work.
 * @author  Milos Kleint
 */
@SuppressWarnings("ClassWithMultipleLoggers")
@ProjectServiceProvider(service=ProjectOpenedHook.class, projectType="org-netbeans-modules-maven")
public class ProjectOpenedHookImpl extends ProjectOpenedHook {
    private static final String PROP_BINARIES_CHECKED = "binariesChecked";
    private static final String PROP_JAVADOC_CHECKED = "javadocChecked";
    private static final String PROP_SOURCE_CHECKED = "sourceChecked";
   
    private final Project proj;
    private TransientRepositories transRepos;
    private final List<URI> uriReferences = new ArrayList<URI>();

    // ui logging
    static final String UI_LOGGER_NAME = "org.netbeans.ui.maven.project"; //NOI18N
    static final Logger UI_LOGGER = Logger.getLogger(UI_LOGGER_NAME);

    static final String USG_LOGGER_NAME = "org.netbeans.ui.metrics.maven"; //NOI18N
    static final Logger USG_LOGGER = Logger.getLogger(USG_LOGGER_NAME);

    private static final Logger LOGGER = Logger.getLogger(ProjectOpenedHookImpl.class.getName());
    private static final AtomicBoolean checkedIndices = new AtomicBoolean();
    
    //here we handle properly the case when someone changes a
    // ../../src path to ../../src2 path in the lifetime of the project.
    private final PropertyChangeListener extRootChangeListener = new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent pce) {
            if (NbMavenProject.PROP_PROJECT.equals(pce.getPropertyName())) {
                NbMavenProjectImpl project = proj.getLookup().lookup(NbMavenProjectImpl.class);
                Set<URI> newuris = getProjectExternalSourceRoots(project);
                synchronized (uriReferences) {
                    Set<URI> olduris = new HashSet<URI>(uriReferences);
                    olduris.removeAll(newuris);
                    newuris.removeAll(uriReferences);
                    for (URI old : olduris) {
                        FileOwnerQuery.markExternalOwner(old, null, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
                    }
                    for (URI nw : newuris) {
                        FileOwnerQuery.markExternalOwner(nw, proj, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
                    }
                    uriReferences.removeAll(olduris);
                    uriReferences.addAll(newuris);
                }
            }
        }
    };
    
    public ProjectOpenedHookImpl(Project proj) {
        this.proj = proj;
        assert checkIssue224012(proj);
    }

    @Messages("UI_MAVEN_PROJECT_OPENED=A Maven project was opened. Appending the project's packaging type.")
    protected @Override void projectOpened() {
        NbMavenProjectImpl project = proj.getLookup().lookup(NbMavenProjectImpl.class);
        project.startHardReferencingMavenPoject();
        checkBinaryDownloads();
        checkSourceDownloads();
        checkJavadocDownloads();
        project.attachUpdater();
        registerWithSubmodules(FileUtil.toFile(proj.getProjectDirectory()), new HashSet<File>());
        //manually register the listener for this project, we know it's loaded and should be listening on changes.
        //registerCoordinates() doesn't attach listeners
        MavenFileOwnerQueryImpl.getInstance().attachProjectListener(project);
        Set<URI> uris = getProjectExternalSourceRoots(project);
        synchronized (uriReferences) {
            for (URI uri : uris) {
                FileOwnerQuery.markExternalOwner(uri, proj, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
                uriReferences.add(uri);
            }
        }
        NbMavenProject watcher = project.getProjectWatcher();
        //XXX: is there an ordering problem? should this be done first right after the project changes, instead of ordinary listener?
        watcher.addPropertyChangeListener(extRootChangeListener);
        
        // register project's classpaths to GlobalPathRegistry
        ProjectSourcesClassPathProvider cpProvider = proj.getLookup().lookup(ProjectSourcesClassPathProvider.class);
        GlobalPathRegistry.getDefault().register(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
        GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
        GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
        GlobalPathRegistry.getDefault().register(ClassPath.EXECUTE, cpProvider.getProjectClassPaths(ClassPath.EXECUTE));
        BatchProblemNotifier.opened(project);
        
        //UI logging.. log what was the packaging type for the opened project..
        LogRecord record = new LogRecord(Level.INFO, "UI_MAVEN_PROJECT_OPENED"); //NOI18N
        record.setLoggerName(UI_LOGGER_NAME); //NOI18N
        record.setParameters(new Object[] {watcher.getPackagingType()});
        record.setResourceBundle(NbBundle.getBundle(ProjectOpenedHookImpl.class));
        UI_LOGGER.log(record);

        //USG logging.. log what was the packaging type for the opened project..
        record = new LogRecord(Level.INFO, "USG_PROJECT_OPEN_MAVEN"); //NOI18N
        record.setLoggerName(USG_LOGGER_NAME); //NOI18N
        record.setParameters(new Object[] {watcher.getPackagingType()});
        USG_LOGGER.log(record);

        if (transRepos == null) {
            transRepos = new TransientRepositories(watcher);
        }
        transRepos.register();

        project.getCopyOnSaveResources().opened();

        //only check for the updates of index, if the indexing was already used.
        if (checkedIndices.compareAndSet(false, true) && existsDefaultIndexLocation() && RepositoryPreferences.isIndexRepositories()) {
            final int freq = RepositoryPreferences.getIndexUpdateFrequency();
            if (freq != RepositoryPreferences.FREQ_NEVER) {
                new RequestProcessor("Maven Repo Index Transfer/Scan").post(new Runnable() { // #138102
                    public @Override void run() {
                        List<RepositoryInfo> ris = RepositoryPreferences.getInstance().getRepositoryInfos();
                        Set<String> doNotIndexRepos = getDoNotIndexRepos();
                        for (final RepositoryInfo ri : ris) {
                            //check this repo can be indexed
                            if ( (!ri.isRemoteDownloadable() && !ri.isLocal()) || doNotIndexRepos.contains(ri.getId())) {
                                LOGGER.log(Level.FINER, "Skipping Index At Startup for :{0}", ri.getId());//NOI18N
                                continue;
                            }
                            boolean run = false;
                            if (freq == RepositoryPreferences.FREQ_STARTUP) {
                                LOGGER.log(Level.FINER, "Index At Startup :{0}", ri.getId());//NOI18N
                                run = true;
                            } else if (freq == RepositoryPreferences.FREQ_ONCE_DAY && checkDiff(ri.getId(), 86400000L)) {
                                LOGGER.log(Level.FINER, "Index Once a Day :{0}", ri.getId());//NOI18N
                                run = true;
                            } else if (freq == RepositoryPreferences.FREQ_ONCE_WEEK && checkDiff(ri.getId(), 604800000L)) {
                                LOGGER.log(Level.FINER, "Index once a Week :{0}", ri.getId());//NOI18N
                                run = true;
                            }
                            if (run && ri.isRemoteDownloadable()) {
                                RepositoryIndexer.indexRepo(ri);
                            }
                        }
                    }
                }, 1000 * 60 * 2);
            }
        }
    }

    private Set<URI> getProjectExternalSourceRoots(NbMavenProjectImpl project) throws IllegalArgumentException {
        Set<URI> uris = new HashSet<URI>();
        Set<URI> toRet = new HashSet<URI>();
        uris.addAll(Arrays.asList(project.getSourceRoots(false)));
        uris.addAll(Arrays.asList(project.getSourceRoots(true)));
        //#167572 in the unlikely event that generated sources are located outside of
        // the project root.
        uris.addAll(Arrays.asList(project.getGeneratedSourceRoots(false)));
        uris.addAll(Arrays.asList(project.getGeneratedSourceRoots(true)));
        URI rootUri = Utilities.toURI(FileUtil.toFile(project.getProjectDirectory()));
        File rootDir = Utilities.toFile(rootUri);
        for (URI uri : uris) {
            if (FileUtilities.getRelativePath(rootDir, Utilities.toFile(uri)) == null) {
                toRet.add(uri);
            }
        }
        return toRet;
    }
    private boolean existsDefaultIndexLocation() {
        File cacheDir = new File(Places.getCacheDirectory(), "mavenindex");//NOI18N
        return cacheDir.exists() && cacheDir.isDirectory();
    }
    private boolean checkDiff(String repoid, long amount) {
        Date date = RepositoryPreferences.getLastIndexUpdate(repoid);
        Date now = new Date();
        LOGGER.log(Level.FINER, "Check Date Diff :{0}", repoid);//NOI18N
        LOGGER.log(Level.FINER, "Last Indexed Date :{0}", SimpleDateFormat.getInstance().format(date));//NOI18N
        LOGGER.log(Level.FINER, "Now :{0}", SimpleDateFormat.getInstance().format(now));//NOI18N
        long diff = now.getTime() - date.getTime();
        LOGGER.log(Level.FINER, "Diff :{0}", diff);//NOI18N
        return (diff < 0 || diff > amount);
    }

    protected @Override void projectClosed() {
        NbMavenProjectImpl project = proj.getLookup().lookup(NbMavenProjectImpl.class);
        //we stop listening for changes in external roots
        //but as before, we keep the latest known roots upon closing..
        project.getProjectWatcher().removePropertyChangeListener(extRootChangeListener);
        synchronized (uriReferences) {
            uriReferences.clear();
        }
        
        project.detachUpdater();
        // unregister project's classpaths to GlobalPathRegistry
        ProjectSourcesClassPathProvider cpProvider = proj.getLookup().lookup(ProjectSourcesClassPathProvider.class);
        GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
        GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
        GlobalPathRegistry.getDefault().unregister(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
        GlobalPathRegistry.getDefault().unregister(ClassPath.EXECUTE, cpProvider.getProjectClassPaths(ClassPath.EXECUTE));
        BatchProblemNotifier.closed(project);
        project.getCopyOnSaveResources().closed();

        if (transRepos != null) { // XXX #212555 projectOpened was not called first?
            transRepos.unregister();
        }
        project.stopHardReferencingMavenPoject();
    }
   
   private void checkBinaryDownloads() {
       MavenSettings.DownloadStrategy ds = MavenSettings.getDefault().getBinaryDownloadStrategy();
       if (ds.equals(MavenSettings.DownloadStrategy.NEVER)) {
           return;
       }

       NbMavenProject watcher = proj.getLookup().lookup(NbMavenProject.class);
       Preferences prefs = ProjectUtils.getPreferences(proj, NbMavenProject.class, false);
       if (ds.equals(MavenSettings.DownloadStrategy.EVERY_OPEN)) {
            watcher.synchronousDependencyDownload();
            prefs.putBoolean(PROP_BINARIES_CHECKED, true);
            try {
                prefs.sync();
            } catch (BackingStoreException ex) {
                Exceptions.printStackTrace(ex);
            }
       } else if (ds.equals(MavenSettings.DownloadStrategy.FIRST_OPEN)) {
           boolean alreadyChecked = prefs.getBoolean(PROP_BINARIES_CHECKED, false);
           if (!alreadyChecked) {
                watcher.synchronousDependencyDownload();
                prefs.putBoolean(PROP_BINARIES_CHECKED, true);
                try {
                    prefs.sync();
                } catch (BackingStoreException ex) {
                    Exceptions.printStackTrace(ex);
                }
           }
       }
   }

   private void checkJavadocDownloads() {
       MavenSettings.DownloadStrategy ds = MavenSettings.getDefault().getJavadocDownloadStrategy();
       if (ds.equals(MavenSettings.DownloadStrategy.NEVER)) {
           return;
       }

       NbMavenProject watcher = proj.getLookup().lookup(NbMavenProject.class);
       Preferences prefs = ProjectUtils.getPreferences(proj, NbMavenProject.class, false);
       if (ds.equals(MavenSettings.DownloadStrategy.EVERY_OPEN)) {
            watcher.triggerSourceJavadocDownload(true);
            prefs.putBoolean(PROP_JAVADOC_CHECKED, true);
            try {
                prefs.sync();
            } catch (BackingStoreException ex) {
                Exceptions.printStackTrace(ex);
            }
       } else if (ds.equals(MavenSettings.DownloadStrategy.FIRST_OPEN)) {
           boolean alreadyChecked = prefs.getBoolean(PROP_JAVADOC_CHECKED, false);
           if (!alreadyChecked) {
                watcher.triggerSourceJavadocDownload(true);
                prefs.putBoolean(PROP_JAVADOC_CHECKED, true);
                try {
                    prefs.sync();
                } catch (BackingStoreException ex) {
                    Exceptions.printStackTrace(ex);
                }
           }
       }
   }

   private void checkSourceDownloads() {
       MavenSettings.DownloadStrategy ds = MavenSettings.getDefault().getSourceDownloadStrategy();
       if (ds.equals(MavenSettings.DownloadStrategy.NEVER)) {
           return;
       }

       NbMavenProject watcher = proj.getLookup().lookup(NbMavenProject.class);
       Preferences prefs = ProjectUtils.getPreferences(proj, NbMavenProject.class, false);
       if (ds.equals(MavenSettings.DownloadStrategy.EVERY_OPEN)) {
            watcher.triggerSourceJavadocDownload(false);
            prefs.putBoolean(PROP_SOURCE_CHECKED, true);
            try {
                prefs.sync();
            } catch (BackingStoreException ex) {
                Exceptions.printStackTrace(ex);
            }
       } else if (ds.equals(MavenSettings.DownloadStrategy.FIRST_OPEN)) {
           boolean alreadyChecked = prefs.getBoolean(PROP_SOURCE_CHECKED, false);
           if (!alreadyChecked) {
                watcher.triggerSourceJavadocDownload(false);
                prefs.putBoolean(PROP_SOURCE_CHECKED, true);
                try {
                    prefs.sync();
                } catch (BackingStoreException ex) {
                    Exceptions.printStackTrace(ex);
                }
           }
       }
   }

    /** Similar to {@link SubprojectProviderImpl#addProjectModules} but more efficient for large numbers of modules. */
    private static void registerWithSubmodules(File basedir, Set<File> registered) { // #200445
        if (!registered.add(basedir)) {
            return;
        }
        File pom = new File(basedir, "pom.xml");
        if (!pom.isFile()) {
            return;
        }
        ModelReader reader = EmbedderFactory.getProjectEmbedder().lookupComponent(ModelReader.class);
        Model model;
        try {
            model = reader.read(pom, Collections.singletonMap(ModelReader.IS_STRICT, false));
        } catch (IOException x) {
            LOGGER.log(Level.FINE, "could not parse " + pom, x);
            return;
        }
        Parent parent = model.getParent();
        String groupId = model.getGroupId();
        if (groupId == null && parent != null) {
            groupId = parent.getGroupId();
        }
        if (groupId == null) {
            LOGGER.log(Level.WARNING, "no groupId in {0}", pom);
            return;
        }
        String artifactId = model.getArtifactId();
        if (artifactId == null && parent != null) {
            artifactId = parent.getArtifactId();
        }
        if (artifactId == null) {
            LOGGER.log(Level.WARNING, "no artifactId in {0}", pom);
            return;
        }
        String version = model.getVersion();
        if (version == null && parent != null) {
            version = parent.getVersion();
        }
        if (version == null) {
            LOGGER.log(Level.WARNING, "no version in {0}", pom);
            return;
        }        
        
        if (groupId.contains("${") || artifactId.contains("${") || version.contains("${")) {
            LOGGER.log(Level.FINE, "Unevaluated groupId/artifactId/version in {0}", basedir);
            FileObject basedirFO = FileUtil.toFileObject(basedir);
            if (basedirFO != null) {
                try {
                    Project p = ProjectManager.getDefault().findProject(basedirFO);
                    if (p != null) {
                        NbMavenProjectImpl nbmp = p.getLookup().lookup(NbMavenProjectImpl.class);
                        if (nbmp != null) {
                            MavenFileOwnerQueryImpl.getInstance().registerProject(nbmp, true);
                        } else {
                            LOGGER.log(Level.FINE, "not a Maven project in {0}", basedir);
                        }
                    } else {
                        LOGGER.log(Level.FINE, "no project in {0}", basedir);
                    }
                } catch (IOException x) {
                    LOGGER.log(Level.FINE, null, x);
                }
            } else {
                LOGGER.log(Level.FINE, "no FileObject for {0}", basedir);
            }
        } else {
            try {
                MavenFileOwnerQueryImpl.getInstance().registerCoordinates(groupId, artifactId, version, Utilities.toURI(basedir).toURL(), true);
            } catch (MalformedURLException x) {
                LOGGER.log(Level.FINE, null, x);
            }
        }
        scanForSubmodulesIn(model, basedir, registered);
        model.getProfiles();
        for (Profile profile : model.getProfiles()) {
            scanForSubmodulesIn(profile, basedir, registered);
        }
    }
    private static void scanForSubmodulesIn(ModelBase projectOrProfile, File basedir, Set<File> registered) throws IllegalArgumentException {
        for (String module : projectOrProfile.getModules()) {
            if (module == null) {
                //#205690 apparently in some rare scenarios module can be null, I was not able to reproduce myself
                //maven itself checks for null value during validation, but at later stages doesn't always check.
                //additional aspect for consideration is that in this case the value is taken from Model class not MavenProject
                continue;
            }
            registerWithSubmodules(FileUtilities.resolveFilePath(basedir, module), registered);
        }
    }

    private boolean checkIssue224012(Project project) {
        if (project instanceof NbMavenProjectImpl) { //unfortunately cannot use lookup here, rendering the assert useless for ergonomics turned on..
            NbMavenProjectImpl im = (NbMavenProjectImpl)project;
            return im.setIssue224012(this, new Exception("Thread:" + Thread.currentThread().getName() + " at " + System.currentTimeMillis() + " for " + im.getPOMFile()));
        }
        return true;
    }

    private Set<String> getDoNotIndexRepos() {
        String st = System.getProperty("maven.indexing.doNotAutoIndex");
        if(st == null || "".equals(st)) {
            return Collections.emptySet();
        }
        String[] repos = st.split(";");
        return new HashSet<>(Arrays.asList(repos));
    }
}
