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

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.*;
import org.apache.maven.properties.internal.EnvironmentUtils;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.BaseLoggerManager;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.api.project.ui.ProjectGroup;
import org.netbeans.api.project.ui.ProjectGroupChangeEvent;
import org.netbeans.api.project.ui.ProjectGroupChangeListener;
import org.netbeans.modules.maven.embedder.impl.ExtensionModule;
import org.openide.filesystems.FileUtil;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbPreferences;
import org.openide.util.RequestProcessor;
import org.openide.util.BaseUtilities;

/**
 * Factory for creating {@link MavenEmbedder}s.
 */
public final class EmbedderFactory {

    public static final String PROP_COMMANDLINE_PATH = "commandLineMavenPath";
    
    //same prop constant in MavenSettings.java
    static final String PROP_DEFAULT_OPTIONS = "defaultOptions"; 
    private static final Set<String> forbidden = new HashSet<String>();
    static {
        forbidden.add("netbeans.logger.console"); //NOI18N
        forbidden.add("java.util.logging.config.class"); //NOI18N
        forbidden.add("netbeans.autoupdate.language"); //NOI18N
        forbidden.add("netbeans.dirs"); //NOI18N
        forbidden.add("netbeans.home"); //NOI18N
        forbidden.add("sun.awt.exception.handler"); //NOI18N
        forbidden.add("org.openide.TopManager.GUI"); //NOI18N
        forbidden.add("org.openide.major.version"); //NOI18N
        forbidden.add("netbeans.autoupdate.variant"); //NOI18N
        forbidden.add("netbeans.dynamic.classpath"); //NOI18N
        forbidden.add("netbeans.autoupdate.country"); //NOI18N
        forbidden.add("netbeans.hash.code"); //NOI18N
        forbidden.add("org.openide.TopManager"); //NOI18N
        forbidden.add("org.openide.version"); //NOI18N
        forbidden.add("netbeans.buildnumber"); //NOI18N
        forbidden.add("javax.xml.parsers.DocumentBuilderFactory"); //NOI18N
        forbidden.add("javax.xml.parsers.SAXParserFactory"); //NOI18N
        forbidden.add("rave.build"); //NOI18N
        forbidden.add("netbeans.accept_license_class"); //NOI18N
        forbidden.add("rave.version"); //NOI18N
        forbidden.add("netbeans.autoupdate.version"); //NOI18N
        forbidden.add("netbeans.importclass"); //NOI18N
        forbidden.add("netbeans.user"); //NOI18N
//        forbidden.add("java.class.path");
//        forbidden.add("https.nonProxyHosts");

    }    

    private static final Logger LOG = Logger.getLogger(EmbedderFactory.class.getName());

    private static MavenEmbedder project;
    private static final AtomicBoolean projectLoaded = new AtomicBoolean(false);
    private static final Object PROJECT_LOCK = new Object();
    private static MavenEmbedder online;
    private static final Object ONLINE_LOCK = new Object();
    
    private static final RequestProcessor RP = new RequestProcessor("Maven Embedder warmup");
    
    private static final RequestProcessor.Task warmupTask = RP.create(new Runnable() {
            @Override
            public void run() {
                //#211158 after being reset, recreate the instance for followup usage. 
                //makes the performance stats of the project embedder after resetting more predictable
                getProjectEmbedder();
            }
        });

    static {
        RP.post(new Runnable() {
            @Override
            public void run() { //#228379
                OpenProjects.getDefault().addProjectGroupChangeListener(new ProjectGroupChangeListener() {
                    @Override
                    public void projectGroupChanging(ProjectGroupChangeEvent event) {
                        resetCachedEmbedders();
                    }

                    @Override
                    public void projectGroupChanged(ProjectGroupChangeEvent event) {
                    }
                });
            }
        });
    }
    
    private EmbedderFactory() {
    }

    /**
     * embedder seems to cache some values..
     */
    public static void resetCachedEmbedders() {
        synchronized (PROJECT_LOCK) {
            projectLoaded.set(false);
            project = null;
        }
        synchronized (ONLINE_LOCK) {
            online = null;
        }
        //just delay a bit in case both MavenSettings.setDefaultOptions and Embedderfactory.setMavenHome are called..
        RP.post(warmupTask, 100);
    }

    public static File getDefaultMavenHome() {
        return InstalledFileLocator.getDefault().locate("maven", "org.netbeans.modules.maven.embedder", false);
    }

    private static Preferences getPreferences() { // compatibility; used to be in MavenSettings
        return NbPreferences.root().node("org/netbeans/modules/maven");
    }
    
    private static Preferences getGroupedPreferences(ProjectGroup grp) { 
        
        if (grp != null) {
            return grp.preferencesForPackage(EmbedderFactory.class);
        }
        return null;
    }

    /**
     * global settings value for maven installation root folder.
     * @return 
     */
    public static @NonNull File getMavenHome() {
        String str =  getPreferences().get(PROP_COMMANDLINE_PATH, null);
        if (str != null) {
            return FileUtil.normalizeFile(new File(str));
        } else {
            return getDefaultMavenHome();
        }
    }
    
    /**
     * maven home (installation root) taken from various places (global settings, project group settings ,...)
     * @return 
     * @since 2.32
     */
    public static @NonNull File getEffectiveMavenHome() {
        ProjectGroup grp = OpenProjects.getDefault().getActiveProjectGroup();       
        return getEffectiveMavenHome(grp);
    } 
    
    /**
     * @since 2.39
     * @param grp
     * @return 
     */
    public static @NonNull File getEffectiveMavenHome(ProjectGroup grp) {
        Preferences grPref = getGroupedPreferences(grp);
        String str =  grPref != null ? grPref.get(PROP_COMMANDLINE_PATH, null) : null;
        if (str == null) {
            str = getPreferences().get(PROP_COMMANDLINE_PATH, null);
        }
        if (str != null) {
            return FileUtil.normalizeFile(new File(str));
        } else {
            return getDefaultMavenHome();
        }
    } 

    public static void setMavenHome(File path) {
        File oldValue = getMavenHome();
        File defValue = getDefaultMavenHome();
        if (oldValue.equals(path) || path == null && oldValue.equals(defValue)) {
            //no change happened, prevent resetting the embedders
            return;
        }
        if (path == null || path.equals(defValue)) {
            getPreferences().remove(PROP_COMMANDLINE_PATH);
        } else {
            getPreferences().put(PROP_COMMANDLINE_PATH, FileUtil.normalizeFile(path).getAbsolutePath());
        }
        resetCachedEmbedders();
    }
    
    public static void setGroupedMavenHome(ProjectGroup grp, File path) {
        File oldValue = getEffectiveMavenHome(grp);     
        File defValue = getMavenHome();
        if (oldValue.equals(path) || path == null && oldValue.equals(defValue)) {
            //no change happened, prevent resetting the embedders
            return;
        }
        Preferences prefs = grp.preferencesForPackage(EmbedderFactory.class);
        if (path == null || path.equals(defValue)) {
            prefs.remove(PROP_COMMANDLINE_PATH);
        } else {
            prefs.put(PROP_COMMANDLINE_PATH, FileUtil.normalizeFile(path).getAbsolutePath());
        }
        resetCachedEmbedders();
    }
    
    
    static Map<String, String> getCustomGlobalUserProperties() {
        //maybe set org.eclipse.aether.ConfigurationProperties.USER_AGENT with netbeans specific value.
        Map<String, String> toRet = new HashMap<String, String>();
        String options = getPreferences().get(PROP_DEFAULT_OPTIONS, "");
        try {
            
            String[] cmdlines = CommandLineUtils.translateCommandline(options);
            if (cmdlines != null) {
                for (String cmd : cmdlines) {
                    if (cmd != null && cmd.startsWith("-D")) {
                        cmd = cmd.substring("-D".length());
                        int ind = cmd.indexOf('=');
                        if (ind > -1) {
                            String key = cmd.substring(0, ind);
                            String val = cmd.substring(ind + 1);
                            toRet.put(key, val);
                        }
                    }
                }
            }
            return toRet;
        } catch (Exception ex) {
            LOG.log(Level.FINE, "cannot parse " + options, ex);
            return Collections.emptyMap();
        }
    }

    private static File getSettingsXml() {
        return new File(getEffectiveMavenHome(), "conf/settings.xml");
    }

    /**
     * #191267: suppresses logging from embedded Maven, since interesting results normally appear elsewhere.
     */
    private static class NbLoggerManager extends BaseLoggerManager {
        protected @Override org.codehaus.plexus.logging.Logger createLogger(String name) {
            int level = levelOf(LOG).intValue();
            return new NbLogger(level <= Level.FINEST.intValue() ? org.codehaus.plexus.logging.Logger.LEVEL_DEBUG :
                  level <= Level.FINER.intValue() ? org.codehaus.plexus.logging.Logger.LEVEL_INFO :
                  level <= Level.FINE.intValue() ? org.codehaus.plexus.logging.Logger.LEVEL_WARN :
                  org.codehaus.plexus.logging.Logger.LEVEL_DISABLED,
                name);
        }
        private Level levelOf(Logger log) {
            Level lvl = log.getLevel();
            if (lvl != null) {
                return lvl;
            } else {
                Logger par = log.getParent();
                if (par != null) {
                    return levelOf(par);
                } else {
                    return Level.INFO;
                }
            }
        }
        private static class NbLogger extends org.codehaus.plexus.logging.AbstractLogger {
            NbLogger(int threshold, String name) {
                super(threshold, name);
                LOG.log(Level.FINEST, "created Plexus logger {0} at threshold {1}", new Object[] {name, threshold});
            }
            private Logger logger() {
                return Logger.getLogger(LOG.getName() + "." + getName());
            }
            public @Override void debug(String m, Throwable t) {
                logger().log(Level.FINEST, m, t);
            }
            public @Override void info(String m, Throwable t) {
                logger().log(Level.FINER, m, t);
            }
            public @Override void warn(String m, Throwable t) {
                logger().log(Level.FINE, m, t);
            }
            public @Override void error(String m, Throwable t) {
                logger().log(Level.FINE, m, t);
            }
            public @Override void fatalError(String m, Throwable t) {
                logger().log(Level.FINE, m, t);
            }
            public @Override org.codehaus.plexus.logging.Logger getChildLogger(String name) {
                return new NbLogger(getThreshold(), getName() + "." + name);
            }
        }
    }

    public static @NonNull MavenEmbedder createProjectLikeEmbedder() throws PlexusContainerException {
        final String mavenCoreRealmId = "plexus.core";
        ContainerConfiguration dpcreq = new DefaultContainerConfiguration()
            .setClassWorld( new ClassWorld(mavenCoreRealmId, EmbedderFactory.class.getClassLoader()) )
            .setClassPathScanning( PlexusConstants.SCANNING_INDEX )
            .setName("maven");
        
        DefaultPlexusContainer pc = new DefaultPlexusContainer(dpcreq, new ExtensionModule());
        pc.setLoggerManager(new NbLoggerManager());

        Properties userprops = new Properties();
        userprops.putAll(getCustomGlobalUserProperties());
        EmbedderConfiguration configuration = new EmbedderConfiguration(pc, cloneStaticProps(), userprops, true, getSettingsXml());
        
        try {
            return new MavenEmbedder(configuration);
            //MEVENIDE-634 make all instances non-interactive
//            WagonManager wagonManager = (WagonManager) embedder.getPlexusContainer().lookup(WagonManager.ROLE);
//            wagonManager.setInteractive(false);
        } catch (ComponentLookupException ex) {
            throw new PlexusContainerException(ex.toString(), ex);
        }
    }

    private static void rethrowThreadDeath(Throwable t) { // #201098
        if (t instanceof ThreadDeath) {
            throw (ThreadDeath) t;
        }
        Throwable t2 = t.getCause();
        if (t2 != null) {
            rethrowThreadDeath(t2);
        }
    }
    
    private static final Properties statics = new Properties();

    static Properties cloneStaticProps() {
        synchronized (statics) {
            if (statics.isEmpty()) { // not yet initialized
                // Now a misnomer, but available to activate profiles only during NB project parse:
                statics.setProperty("netbeans.execution", "true"); // NOI18N
                EmbedderFactory.fillEnvVars(statics);
                statics.putAll(excludeNetBeansProperties(System.getProperties()));
            }
            Properties toRet = new Properties();
            toRet.putAll(statics);
            return toRet;
        }
    }
    
    @SuppressWarnings("element-type-mismatch")
    static Properties excludeNetBeansProperties(Properties props) {
        Properties toRet = new Properties();
        for (Map.Entry<Object,Object> entry : props.entrySet()) {
            if (!forbidden.contains(entry.getKey())) {
                toRet.put(entry.getKey(), entry.getValue());
            }
        }
        return toRet;
    }
    
   
    
    /**
     * a simple way to tell if projectEmbedder is loaded or not.
     * just for performance reasons if someone wants to skip processing because of risk of loading the embedder.
     * Mostly applies to global services only.
     * @return 
     * @since 2.35
     */
    public static boolean isProjectEmbedderLoaded() {
        return projectLoaded.get();
    }

    public static @NonNull MavenEmbedder getProjectEmbedder() {
        synchronized (PROJECT_LOCK) {
            if (project == null) {
                try {
                    project = createProjectLikeEmbedder();
                } catch (PlexusContainerException ex) {
                    rethrowThreadDeath(ex);
                    throw new IllegalStateException(ex);
                }
                projectLoaded.set(true);
            }
            return project;
        }
    }

    public static @NonNull MavenEmbedder getOnlineEmbedder() {
        synchronized (ONLINE_LOCK) {
            if (online == null) {
                try {
                    online = createOnlineEmbedder();
                } catch (PlexusContainerException ex) {
                    rethrowThreadDeath(ex);
                    throw new IllegalStateException(ex);
                }
            }
            return online;
        }
    }

    /*public*/ @NonNull static MavenEmbedder createOnlineEmbedder() throws PlexusContainerException {
        final String mavenCoreRealmId = "plexus.core";
        ContainerConfiguration dpcreq = new DefaultContainerConfiguration()
            .setClassWorld( new ClassWorld(mavenCoreRealmId, EmbedderFactory.class.getClassLoader()) )
            .setClassPathScanning( PlexusConstants.SCANNING_INDEX )
            .setName("maven");

        DefaultPlexusContainer pc = new DefaultPlexusContainer(dpcreq);
        pc.setLoggerManager(new NbLoggerManager());

        Properties userprops = new Properties();
        userprops.putAll(getCustomGlobalUserProperties());
        EmbedderConfiguration req = new EmbedderConfiguration(pc, cloneStaticProps(), userprops, false, getSettingsXml());

//        //TODO remove explicit activation
//        req.addActiveProfile("netbeans-public").addActiveProfile("netbeans-private"); //NOI18N


//        req.setConfigurationCustomizer(new ContainerCustomizer() {
//
//            public void customize(PlexusContainer plexusContainer) {
//                    //MEVENIDE-634
//                    ComponentDescriptor desc = plexusContainer.getComponentDescriptor(KnownHostsProvider.ROLE, "file"); //NOI18N
//                    desc.getConfiguration().getChild("hostKeyChecking").setValue("no"); //NOI18N
//
//                    //MEVENIDE-634
//                    desc = plexusContainer.getComponentDescriptor(KnownHostsProvider.ROLE, "null"); //NOI18N
//                    desc.getConfiguration().getChild("hostKeyChecking").setValue("no"); //NOI18N
//            }
//        });

        try {
            return new MavenEmbedder(req);
            //MEVENIDE-634 make all instances non-interactive
//            WagonManager wagonManager = (WagonManager) embedder.getPlexusContainer().lookup(WagonManager.ROLE);
//            wagonManager.setInteractive(false);
        } catch (ComponentLookupException ex) {
            throw new PlexusContainerException(ex.toString(), ex);
        }
//            try {
//                //MEVENIDE-634 make all instances non-interactive
//                WagonManager wagonManager = (WagonManager) embedder.getPlexusContainer().lookup(WagonManager.ROLE);
//                wagonManager.setInteractive( false );
//                wagonManager.setDownloadMonitor(new ProgressTransferListener());
//            } catch (ComponentLookupException ex) {
//                ErrorManager.getDefault().notify(ex);
//            }
    }

    /**
     * using this method one creates an ArtifactRepository instance with injected mirrors and proxies
     * @param embedder
     * @param url
     * @param id
     * @return 
     * @deprecated use MavenEmbedder.createRemoteRepository
     */
    @Deprecated
    public static ArtifactRepository createRemoteRepository(MavenEmbedder embedder, String url, String id) {
        return embedder.createRemoteRepository(url, id);
    }

    /**
     * Creates a list of POM models in an inheritance lineage.
     * Each resulting model is "raw", so contains no interpolation or inheritance.
     * In particular beware that groupId and/or version may be null if inherited from a parent; use {@link Model#getParent} to resolve.
     * @param pom a POM to inspect
     * @param embedder an embedder to use
     * @return a list of models, starting with the specified POM, going through any parents, finishing with the Maven superpom (with a null artifactId)
     * @throws ModelBuildingException if the POM or parents could not even be parsed; warnings are not reported
     * @deprecated use MavenEmbedder.createModelLineage
     */
    @Deprecated
    public static List<Model> createModelLineage(File pom, MavenEmbedder embedder) throws ModelBuildingException {
        return embedder.createModelLineage(pom);
    }

    /**
     * Maven assumes the env vars are included in execution properties with the "env." prefix.
     * @param properties
     * @return 
     * @see EnvironmentUtils#addEnvVars
     */
    public static Properties fillEnvVars(Properties properties) {
        for (Map.Entry<String,String> entry : System.getenv().entrySet()) {
            String key = entry.getKey();
            if (BaseUtilities.isWindows()) {
                key = key.toUpperCase(Locale.ENGLISH);
            }
            properties.setProperty("env." + key, entry.getValue());
        }
        return properties;
    }
}
