package org.apache.maven.archetype.source;

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

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.maven.archetype.catalog.Archetype;
import org.apache.maven.archetype.catalog.ArchetypeCatalog;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.project.ProjectBuildingRequest;
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.UnsupportedProtocolException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.WagonException;
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.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;

/**
 * @author Jason van Zyl
 */
@Component( role = ArchetypeDataSource.class, hint = "remote-catalog" )
public class RemoteCatalogArchetypeDataSource extends CatalogArchetypeDataSource implements ArchetypeDataSource
{
    @Requirement
    private Map<String, Wagon> wagons;
    
    @Requirement
    private LegacySupport legacySupport;

    @Requirement
    private SettingsDecrypter settingsDecrypter;

//    Should be used for mirror/proxy/authentication
//    available since M3.2.3
//    @Requirement
//    private MavenRepositorySystem;

    /**
     * Id of the repository used to download catalog file. Proxy or authentication info can
     * be setup in settings.xml.
     */
    public static final String ARCHETYPE_REPOSITORY_ID = "archetype";

    public static final String CENTRAL_REPOSITORY_ID = "central";

    @Override
    public ArchetypeCatalog getArchetypeCatalog( ProjectBuildingRequest buildingRequest )
        throws ArchetypeDataSourceException
    {
        // With M3 artifactRepositories are already injected with their mirror, including the new id
        // First look for mirrorId of both 'central' and 'archetype'
        final String archetypeRepoId;
        Mirror archetypeMirror = getMirror( ARCHETYPE_REPOSITORY_ID );
        if ( archetypeMirror != null )
        {
            archetypeRepoId = archetypeMirror.getId();
        }
        else
        {
            archetypeRepoId = ARCHETYPE_REPOSITORY_ID;
        }
        
        final String centralRepoId;
        Mirror centralMirror = getMirror( CENTRAL_REPOSITORY_ID );
        if ( centralMirror != null )
        {
            centralRepoId = centralMirror.getId();
        }
        else
        {
            centralRepoId = CENTRAL_REPOSITORY_ID;
        }
        
        ArtifactRepository centralRepository = null;
        ArtifactRepository archetypeRepository = null;
        for ( ArtifactRepository remoteRepository : buildingRequest.getRemoteRepositories() )
        {
            if ( archetypeRepoId.equals( remoteRepository.getId() ) )
            {
                archetypeRepository = remoteRepository;
                break;
            }
            else if ( centralRepoId.equals( remoteRepository.getId() ) )
            {
                centralRepository = remoteRepository;
            }
        }

        if ( archetypeRepository == null )
        {
            archetypeRepository = centralRepository;
        }

        try
        {
            return downloadCatalog( archetypeRepository );
        }
        catch ( IOException e )
        {
            throw new ArchetypeDataSourceException( e );
        }
        catch ( WagonException e )
        {
            throw new ArchetypeDataSourceException( e );
        }
    }

    @Override
    public void updateCatalog( ProjectBuildingRequest buildingRequest, Archetype archetype )
        throws ArchetypeDataSourceException
    {
        throw new ArchetypeDataSourceException( "Not supported yet." );
    }

    private ArchetypeCatalog downloadCatalog( ArtifactRepository repository )
        throws WagonException, IOException, ArchetypeDataSourceException
    {
        getLogger().debug( "Searching for remote catalog: " + repository.getUrl() + "/" + ARCHETYPE_CATALOG_FILENAME );

        // We use wagon to take advantage of a Proxy that has already been setup in a Maven environment.
        Repository wagonRepository = new Repository( repository.getId(), repository.getUrl() );
        
        AuthenticationInfo authInfo = getAuthenticationInfo( wagonRepository.getId() );
        ProxyInfo proxyInfo = getProxy( wagonRepository.getProtocol() );

        Wagon wagon = getWagon( wagonRepository );

        File catalog = File.createTempFile( "archetype-catalog", ".xml" );
        try
        {
            wagon.connect( wagonRepository, authInfo, proxyInfo );
            wagon.get( ARCHETYPE_CATALOG_FILENAME, catalog );

            return readCatalog( ReaderFactory.newXmlReader( catalog ) );
        }
        finally
        {
            disconnectWagon( wagon );
            catalog.delete();
        }
    }

    private void disconnectWagon( Wagon wagon )
    {
        try
        {
            wagon.disconnect();
        }
        catch ( Exception e )
        {
            getLogger().warn( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
        }
    }

    // 
    
    private Wagon getWagon( Repository repository )
        throws UnsupportedProtocolException
    {
        return getWagon( repository.getProtocol() );
    }

    private Wagon getWagon( String protocol )
        throws UnsupportedProtocolException
    {
        if ( protocol == null )
        {
            throw new UnsupportedProtocolException( "Unspecified protocol" );
        }

        String hint = protocol.toLowerCase( java.util.Locale.ENGLISH );

        Wagon wagon = wagons.get( hint );
        if ( wagon == null )
        {
            throw new UnsupportedProtocolException( "Cannot find wagon which supports the requested protocol: "
                + protocol );
        }

        return wagon;
    }
    
    private AuthenticationInfo getAuthenticationInfo( String id )
    {
        MavenSession session = legacySupport.getSession();

        if ( session != null && id != null )
        {
            MavenExecutionRequest request = session.getRequest();

            if ( request != null )
            {
                List<Server> servers = request.getServers();

                if ( servers != null )
                {
                    for ( Server server : servers )
                    {
                        if ( id.equalsIgnoreCase( server.getId() ) )
                        {
                            SettingsDecryptionResult result =
                                settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( server ) );
                            server = result.getServer();

                            AuthenticationInfo authInfo = new AuthenticationInfo();
                            authInfo.setUserName( server.getUsername() );
                            authInfo.setPassword( server.getPassword() );
                            authInfo.setPrivateKey( server.getPrivateKey() );
                            authInfo.setPassphrase( server.getPassphrase() );

                            return authInfo;
                        }
                    }
                }
            }
        }

        // empty one to prevent NPE
       return new AuthenticationInfo();
    }

    private ProxyInfo getProxy( String protocol )
    {
        MavenSession session = legacySupport.getSession();

        if ( session != null && protocol != null )
        {
            MavenExecutionRequest request = session.getRequest();

            if ( request != null )
            {
                List<Proxy> proxies = request.getProxies();

                if ( proxies != null )
                {
                    for ( Proxy proxy : proxies )
                    {
                        if ( proxy.isActive() && protocol.equalsIgnoreCase( proxy.getProtocol() ) )
                        {
                            SettingsDecryptionResult result =
                                settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) );
                            proxy = result.getProxy();

                            ProxyInfo proxyInfo = new ProxyInfo();
                            proxyInfo.setHost( proxy.getHost() );
                            proxyInfo.setType( proxy.getProtocol() );
                            proxyInfo.setPort( proxy.getPort() );
                            proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
                            proxyInfo.setUserName( proxy.getUsername() );
                            proxyInfo.setPassword( proxy.getPassword() );

                            return proxyInfo;
                        }
                    }
                }
            }
        }

        return null;
    }
    
    private Mirror getMirror( String repoId )
    {
        MavenSession session = legacySupport.getSession();

        MavenExecutionRequest request = session.getRequest();

        if ( request != null )
        {
            return getMirror( repoId, request.getMirrors() );
        }
        
        return null;
    }
    
    private static final String WILDCARD = "*";

    private static final String EXTERNAL_WILDCARD = "external:*";

    private Mirror getMirror( String repoId, List<Mirror> mirrors )
    {
        if ( repoId != null && mirrors != null )
        {
            for ( Mirror mirror : mirrors )
            {
                if ( repoId.equals( mirror.getMirrorOf() ) )
                {
                    return mirror;
                }
            }

            for ( Mirror mirror : mirrors )
            {
                if ( matchPattern( repoId, mirror.getMirrorOf() ) )
                {
                    return mirror;
                }
            }
        }

        return null;
    }

    /**
     * This method checks if the pattern matches the originalRepository. Valid patterns: * =
     * everything external:* = everything not on the localhost and not file based. repo,repo1 = repo
     * or repo1 *,!repo1 = everything except repo1
     *
     * @param originalId to compare for a match.
     * @param pattern used for match. Currently only '*' is supported.
     * @return true if the repository is a match to this pattern.
     */
    static boolean matchPattern( String originalId, String pattern )
    {
        boolean result = false;

        // simple checks first to short circuit processing below.
        if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
        {
            result = true;
        }
        else
        {
            // process the list
            String[] repos = pattern.split( "," );
            for ( String repo : repos )
            {
                // see if this is a negative match
                if ( repo.length() > 1 && repo.startsWith( "!" ) )
                {
                    if ( repo.substring( 1 ).equals( originalId ) )
                    {
                        // explicitly exclude. Set result and stop processing.
                        result = false;
                        break;
                    }
                }
                // check for exact match
                else if ( repo.equals( originalId ) )
                {
                    result = true;
                    break;
                }
                // check for external:*
                else if ( EXTERNAL_WILDCARD.equals( repo ) )
                {
                    result = true;
                    // don't stop processing in case a future segment explicitly excludes this repo
                }
                else if ( WILDCARD.equals( repo ) )
                {
                    result = true;
                    // don't stop processing in case a future segment explicitly excludes this repo
                }
            }
        }
        return result;
    }



    static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
    {
        return matchesLayout( repository.getLayout().getId(), mirror.getMirrorOfLayouts() );
    }

    /**
     * Checks whether the layouts configured for a mirror match with the layout of the repository.
     *
     * @param repoLayout The layout of the repository, may be {@code null}.
     * @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
     * @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
     *         {@code false} otherwise.
     */
    static boolean matchesLayout( String repoLayout, String mirrorLayout )
    {
        boolean result = false;

        // simple checks first to short circuit processing below.
        if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
        {
            result = true;
        }
        else if ( mirrorLayout.equals( repoLayout ) )
        {
            result = true;
        }
        else
        {
            // process the list
            String[] layouts = mirrorLayout.split( "," );
            for ( String layout : layouts )
            {
                // see if this is a negative match
                if ( layout.length() > 1 && layout.startsWith( "!" ) )
                {
                    if ( layout.substring( 1 ).equals( repoLayout ) )
                    {
                        // explicitly exclude. Set result and stop processing.
                        result = false;
                        break;
                    }
                }
                // check for exact match
                else if ( layout.equals( repoLayout ) )
                {
                    result = true;
                    break;
                }
                else if ( WILDCARD.equals( layout ) )
                {
                    result = true;
                    // don't stop processing in case a future segment explicitly excludes this repo
                }
            }
        }

        return result;
    }
}
