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

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.repository.MirrorSelector;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.WagonException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.util.FileUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.netbeans.modules.maven.api.archetype.Archetype;
import org.netbeans.modules.maven.api.archetype.ArchetypeProvider;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.openide.modules.Places;
import org.openide.util.NbCollections;
import org.openide.util.Utilities;
import org.openide.util.lookup.ServiceProvider;

/**
 * list of archetypes coming from an archetype catalog
 * @author mkleint
 */
public abstract class CatalogRepoProvider implements ArchetypeProvider {

    private static final String EL_ARCHETYPES = "archetypes"; //NOI18N
    private static final String EL_ARCHETYPE = "archetype"; //NOI18N
    private static final String EL_ARTIFACTID = "artifactId"; //NOI18N
    private static final String EL_DESCRIPTION = "description";
    private static final String EL_GROUPID = "groupId"; //NOI18N
    private static final String EL_REPOSITORY = "repository"; //NOI18N
    private static final String EL_VERSION = "version"; //NOI18N

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

    protected CatalogRepoProvider() {}

    protected abstract URL file() throws IOException;

    protected abstract String repository();

    public @Override List<Archetype> getArchetypes() {
        try {
            return getArchetypes(file(), repository());
        } catch (IOException ex) {
            LOG.log(Level.INFO, null, ex);
            return Collections.emptyList();
        }
    }
    
    static List<Archetype> getArchetypes(URL file, String repository) {
        List<Archetype> toRet = new ArrayList<Archetype>();
        try {
            if (file == null) {
                return toRet;
            }
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(file);
            Element root = doc.getRootElement();
            Namespace ns = root.getNamespace(); // should be http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0 but missing in older copies
            Element list = root.getChild(EL_ARCHETYPES, ns);
            if (list != null) {
                for (Element el : NbCollections.checkedListByCopy(list.getChildren(EL_ARCHETYPE, ns), Element.class, true)) {
                    String grId = el.getChildText(EL_GROUPID, ns);
                    String artId = el.getChildText(EL_ARTIFACTID, ns);
                    String ver = el.getChildText(EL_VERSION, ns);
                    String repo = el.getChildText(EL_REPOSITORY, ns);
                    String desc = el.getChildText(EL_DESCRIPTION, ns);
                    Archetype archetype = new Archetype(false);
                    if (grId != null && artId != null && ver != null) {
                        archetype.setArtifactId(artId);
                        archetype.setGroupId(grId);
                        archetype.setVersion(ver);
                        if (repo != null) {
                            archetype.setRepository(repo);
                        } else {
                            archetype.setRepository(repository);
                        }
                        if (desc != null) {
                            archetype.setDescription(desc);
                        }
                        toRet.add(archetype);
                    }
                }
            }
        } catch (IOException exc) {
            LOG.log(Level.INFO, null, exc);
        } catch (JDOMException exc) {
            LOG.log(Level.INFO, null, exc);
        }
        return toRet;
    }

    @ServiceProvider(service=ArchetypeProvider.class, position=100)
    public static class LocalCatalogRepoProvider extends CatalogRepoProvider {

        @Override protected URL file() throws IOException {
            File f = new File(RepositorySystem.userMavenConfigurationHome, "archetype-catalog.xml"); //NOI18N
            return f.isFile() ? Utilities.toURI(f).toURL() : null;
        }

        @Override protected String repository() {
            return RepositorySystem.DEFAULT_LOCAL_REPO_ID;
        }

    }

    // one day period for updating downloaded/cached archetype catalogs
    private static final long ARCHETYPE_TIMEOUT = 1000 * 60 * 60 * 24; // * 7;
    
    @ServiceProvider(service=ArchetypeProvider.class, position=50) //has to come before the localCatalogProvider one..
    public static class RemoteCatalogProvider implements ArchetypeProvider {

        @Override
        public List<Archetype> getArchetypes() {
            File root = Places.getCacheSubdirectory("mavenarchetypes"); //NOI18N
            ArrayList<Archetype> toRet = new ArrayList<Archetype>();
            MavenEmbedder embedder = EmbedderFactory.getOnlineEmbedder();
            SettingsDecryptionResult settings = embedder.lookupComponent(SettingsDecrypter.class).decrypt(new DefaultSettingsDecryptionRequest(embedder.getSettings()));
            
            for (RepositoryInfo info : RepositoryPreferences.getInstance().getRepositoryInfos()) {
                if (info.isRemoteDownloadable()) {
                    File catalog = new File(new File( root, info.getId()), "archetype-catalog.xml"); //NOI18N
                    boolean download = false;
                    if (!catalog.exists()) {
                        download = true;
                    } else {
                        long lastM = catalog.lastModified();
                        if (lastM == 0) {
                            download = true;
                        } else if (lastM - System.currentTimeMillis() > ARCHETYPE_TIMEOUT) {
                            download = true;
                        }
                    }
                    
                    if (download) {
                        download(info.getId(), info.getRepositoryUrl(), catalog, settings, embedder);
                    }
                    
                    if (catalog.exists()) {
                        try {
                            toRet.addAll(CatalogRepoProvider.getArchetypes(Utilities.toURI(catalog).toURL(), info.getRepositoryUrl()));
                        } catch (MalformedURLException ex) {
                            LOG.log(Level.INFO, null, ex);
                        }
                    }
                }
            }
            
            return toRet;
        }

        private void download(String id, String url, File catalog, SettingsDecryptionResult settings, MavenEmbedder embedder) {
            String baseurl = url;
            String repoId = id;
            try {
                catalog.getParentFile().mkdirs();
                AuthenticationInfo wagonAuth = null;
//        //this comes from maven-compat
                MirrorSelector mrri = embedder.lookupComponent(MirrorSelector.class);

                // handle mirroring
                ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) embedder.getPlexus().lookup(ArtifactRepositoryLayout.ROLE, "default"); //NOI18N
                ArtifactRepositoryFactory arf = embedder.lookupComponent(ArtifactRepositoryFactory.class);

                //what is the update policy?
                ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy(true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY);
                ArtifactRepository art = arf.createArtifactRepository(repoId, baseurl, layout, policy, policy);
                Mirror mirr = mrri.getMirror(art, embedder.getSettings().getMirrors());
                if (mirr != null) {
                    baseurl = mirr.getUrl();
                    repoId = mirr.getId();
                }

                for (Server server : settings.getServers()) {
                    if (repoId.equals(server.getId())) {
                        wagonAuth = new AuthenticationInfo();
                        wagonAuth.setUserName(server.getUsername());
                        wagonAuth.setPassword(server.getPassword());
                        wagonAuth.setPassphrase(server.getPassphrase());
                        wagonAuth.setPrivateKey(server.getPrivateKey());
                        break;
                    }
                }
                String protocol = URI.create(baseurl).getScheme();
                ProxyInfo wagonProxy = null;
                for (Proxy proxy : settings.getProxies()) {
                    if (proxy.isActive()) {
                        wagonProxy = new ProxyInfo();
                        wagonProxy.setHost(proxy.getHost());
                        wagonProxy.setPort(proxy.getPort());
                        wagonProxy.setNonProxyHosts(proxy.getNonProxyHosts());
                        wagonProxy.setUserName(proxy.getUsername());
                        wagonProxy.setPassword(proxy.getPassword());
                        wagonProxy.setType(protocol);
                        break;
                    }
                }
                Wagon wagon = embedder.getPlexus().lookup(Wagon.class, protocol);
                assert wagon != null;

                Repository repository = new Repository(repoId, baseurl);

                try {

                    // when working in the context of Maven, the WagonManager is already
                    // populated with proxy information from the Maven environment

                    if (wagonAuth != null) {
                        if (wagonProxy != null) {
                            wagon.connect(repository, wagonAuth, wagonProxy);
                        } else {
                            wagon.connect(repository, wagonAuth);
                        }
                    } else {
                        if (wagonProxy != null) {
                            wagon.connect(repository, wagonProxy);
                        } else {
                            wagon.connect(repository);
                        }
                    }

                    File temp = File.createTempFile("maven", "catalog"); //NOI18N
                    try {
                        wagon.get("archetype-catalog.xml", temp); //NOI18N
                        //only overwrite the old file or create file if the content is there.
                        if (temp.exists() && temp.length() > 0) {
                            FileUtils.copyFile(temp, catalog);
                            temp.delete();
                        }
                    } finally {
                        wagon.disconnect();
                    }

                } catch (AuthenticationException ex) {
                    String msg = "Authentication exception connecting to " + repository;  //NOI18N
                    throw new IOException(msg, ex);
                } catch (WagonException ex) {
                    String msg = "Wagon exception connecting to " + repository;  //NOI18N
                    throw new IOException(msg, ex);
                } finally {
                    try {
                        wagon.disconnect();
                    } catch (ConnectionException ex) {
                        String msg = "Wagon exception disconnecting from " + repository; //NOI18N
                        throw new IOException(msg, ex);
                    }
                }
            } catch (ComponentLookupException ex) {
                LOG.log(Level.FINE, null, ex);
            } catch (IOException io) {
                LOG.log(Level.INFO, null, io);
            }

        }
    }
}
