package org.apache.maven.wagon.providers.http;

/*
 * 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 org.apache.commons.io.IOUtils;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.InputData;
import org.apache.maven.wagon.OutputData;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.StreamWagon;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.events.TransferEvent;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.resource.Resource;
import org.apache.maven.wagon.shared.http.EncodingUtil;
import org.apache.maven.wagon.shared.http.HtmlFileListParser;
import org.codehaus.plexus.util.Base64;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DeflaterInputStream;
import java.util.zip.GZIPInputStream;

import static java.lang.Integer.parseInt;
import static org.apache.maven.wagon.shared.http.HttpMessageUtils.UNKNOWN_STATUS_CODE;
import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatAuthorizationMessage;
import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatResourceDoesNotExistMessage;
import static org.apache.maven.wagon.shared.http.HttpMessageUtils.formatTransferFailedMessage;

/**
 * LightweightHttpWagon, using JDK's HttpURLConnection.
 *
 * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
 * @plexus.component role="org.apache.maven.wagon.Wagon" role-hint="http" instantiation-strategy="per-lookup"
 * @see HttpURLConnection
 */
public class LightweightHttpWagon
    extends StreamWagon
{
    private boolean preemptiveAuthentication;

    private HttpURLConnection putConnection;

    private Proxy proxy = Proxy.NO_PROXY;

    private static final Pattern IOEXCEPTION_MESSAGE_PATTERN = Pattern.compile( "Server returned HTTP response code: "
            + "(\\d\\d\\d) for URL: (.*)" );

    public static final int MAX_REDIRECTS = 10;

    /**
     * Whether to use any proxy cache or not.
     *
     * @plexus.configuration default="false"
     */
    private boolean useCache;

    /**
     * @plexus.configuration
     */
    private Properties httpHeaders;

    /**
     * @plexus.requirement
     */
    private volatile LightweightHttpWagonAuthenticator authenticator;

    /**
     * Builds a complete URL string from the repository URL and the relative path of the resource passed.
     *
     * @param resource the resource to extract the relative path from.
     * @return the complete URL
     */
    private String buildUrl( Resource resource )
    {
        return EncodingUtil.encodeURLToString( getRepository().getUrl(), resource.getName() );
    }

    public void fillInputData( InputData inputData )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        Resource resource = inputData.getResource();

        String visitingUrl = buildUrl( resource );

        List<String> visitedUrls = new ArrayList<>();

        for ( int redirectCount = 0; redirectCount < MAX_REDIRECTS; redirectCount++ )
        {
            if ( visitedUrls.contains( visitingUrl ) )
            {
                // TODO add a test for this message
                throw new TransferFailedException( "Cyclic http redirect detected. Aborting! " + visitingUrl );
            }
            visitedUrls.add( visitingUrl );

            URL url = null;
            try
            {
                url = new URL( visitingUrl );
            }
            catch ( MalformedURLException e )
            {
                // TODO add test for this
                throw new ResourceDoesNotExistException( "Invalid repository URL: " + e.getMessage(), e );
            }

            HttpURLConnection urlConnection = null;

            try
            {
                urlConnection = ( HttpURLConnection ) url.openConnection( this.proxy );
            }
            catch ( IOException e )
            {
                // TODO: add test for this
                String message = formatTransferFailedMessage( visitingUrl, UNKNOWN_STATUS_CODE,
                        null, getProxyInfo() );
                // TODO include e.getMessage appended to main message?
                throw new TransferFailedException( message, e );
            }

            try
            {

                urlConnection.setRequestProperty( "Accept-Encoding", "gzip,deflate" );
                if ( !useCache )
                {
                    urlConnection.setRequestProperty( "Pragma", "no-cache" );
                }

                addHeaders( urlConnection );

                // TODO: handle all response codes
                int responseCode = urlConnection.getResponseCode();
                String reasonPhrase = urlConnection.getResponseMessage();

                if ( responseCode == HttpURLConnection.HTTP_FORBIDDEN
                        || responseCode == HttpURLConnection.HTTP_UNAUTHORIZED
                        || responseCode == HttpURLConnection.HTTP_PROXY_AUTH )
                {
                    throw new AuthorizationException( formatAuthorizationMessage( buildUrl( resource ),
                            responseCode, reasonPhrase, getProxyInfo() ) );
                }
                if ( responseCode == HttpURLConnection.HTTP_MOVED_PERM
                        || responseCode == HttpURLConnection.HTTP_MOVED_TEMP )
                {
                    visitingUrl = urlConnection.getHeaderField( "Location" );
                    continue;
                }

                InputStream is = urlConnection.getInputStream();
                String contentEncoding = urlConnection.getHeaderField( "Content-Encoding" );
                boolean isGZipped = contentEncoding != null && "gzip".equalsIgnoreCase( contentEncoding );
                if ( isGZipped )
                {
                    is = new GZIPInputStream( is );
                }
                boolean isDeflated = contentEncoding != null && "deflate".equalsIgnoreCase( contentEncoding );
                if ( isDeflated )
                {
                    is = new DeflaterInputStream( is );
                }
                inputData.setInputStream( is );
                resource.setLastModified( urlConnection.getLastModified() );
                resource.setContentLength( urlConnection.getContentLength() );
                break;

            }
            catch ( FileNotFoundException e )
            {
                // this could be 404 Not Found or 410 Gone - we don't have access to which it was.
                // TODO: 2019-10-03 url used should list all visited/redirected urls, not just the original
                throw new ResourceDoesNotExistException( formatResourceDoesNotExistMessage( buildUrl( resource ),
                        UNKNOWN_STATUS_CODE, null, getProxyInfo() ), e );
            }
            catch ( IOException originalIOException )
            {
                throw convertHttpUrlConnectionException( originalIOException, urlConnection, buildUrl( resource ) );
            }

        }

    }

    private void addHeaders( HttpURLConnection urlConnection )
    {
        if ( httpHeaders != null )
        {
            for ( Object header : httpHeaders.keySet() )
            {
                urlConnection.setRequestProperty( (String) header, httpHeaders.getProperty( (String) header ) );
            }
        }
        setAuthorization( urlConnection );
    }

    private void setAuthorization( HttpURLConnection urlConnection )
    {
        if ( preemptiveAuthentication && authenticationInfo != null && authenticationInfo.getUserName() != null )
        {
            String credentials = authenticationInfo.getUserName() + ":" + authenticationInfo.getPassword();
            String encoded = new String( Base64.encodeBase64( credentials.getBytes() ) );
            urlConnection.setRequestProperty( "Authorization", "Basic " + encoded );
        }
    }

    public void fillOutputData( OutputData outputData )
        throws TransferFailedException
    {
        Resource resource = outputData.getResource();
        try
        {
            URL url = new URL( buildUrl( resource ) );
            putConnection = (HttpURLConnection) url.openConnection( this.proxy );

            addHeaders( putConnection );

            putConnection.setRequestMethod( "PUT" );
            putConnection.setDoOutput( true );

            if ( resource.getContentLength() != -1 )
            {
                putConnection.setFixedLengthStreamingMode( resource.getContentLength() );
            }
            else
            {
                putConnection.setChunkedStreamingMode( 0 );
            }
            outputData.setOutputStream( putConnection.getOutputStream() );
        }
        catch ( IOException e )
        {
            throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
        }
    }

    protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
    {
        try
        {
            String reasonPhrase = putConnection.getResponseMessage();
            int statusCode = putConnection.getResponseCode();

            switch ( statusCode )
            {
                // Success Codes
                case HttpURLConnection.HTTP_OK: // 200
                case HttpURLConnection.HTTP_CREATED: // 201
                case HttpURLConnection.HTTP_ACCEPTED: // 202
                case HttpURLConnection.HTTP_NO_CONTENT: // 204
                    break;

                case HttpURLConnection.HTTP_FORBIDDEN:
                case HttpURLConnection.HTTP_UNAUTHORIZED:
                case HttpURLConnection.HTTP_PROXY_AUTH:
                    throw new AuthorizationException( formatAuthorizationMessage( buildUrl( resource ), statusCode,
                            reasonPhrase, getProxyInfo() ) );

                case HttpURLConnection.HTTP_NOT_FOUND:
                    throw new ResourceDoesNotExistException( formatResourceDoesNotExistMessage( buildUrl( resource ),
                            statusCode, reasonPhrase, getProxyInfo() ) );

                // add more entries here
                default:
                    throw new TransferFailedException( formatTransferFailedMessage( buildUrl( resource ),
                            statusCode, reasonPhrase, getProxyInfo() ) ) ;
            }
        }
        catch ( IOException e )
        {
            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
            throw convertHttpUrlConnectionException( e, putConnection, buildUrl( resource ) );
        }
    }

    protected void openConnectionInternal()
        throws ConnectionException, AuthenticationException
    {
        final ProxyInfo proxyInfo = getProxyInfo( "http", getRepository().getHost() );
        if ( proxyInfo != null )
        {
            this.proxy = getProxy( proxyInfo );
            this.proxyInfo = proxyInfo;
        }
        authenticator.setWagon( this );

        boolean usePreemptiveAuthentication =
            Boolean.getBoolean( "maven.wagon.http.preemptiveAuthentication" ) || Boolean.parseBoolean(
                repository.getParameter( "preemptiveAuthentication" ) ) || this.preemptiveAuthentication;

        setPreemptiveAuthentication( usePreemptiveAuthentication );
    }

    @SuppressWarnings( "deprecation" )
    public PasswordAuthentication requestProxyAuthentication()
    {
        if ( proxyInfo != null && proxyInfo.getUserName() != null )
        {
            String password = "";
            if ( proxyInfo.getPassword() != null )
            {
                password = proxyInfo.getPassword();
            }
            return new PasswordAuthentication( proxyInfo.getUserName(), password.toCharArray() );
        }
        return null;
    }

    public PasswordAuthentication requestServerAuthentication()
    {
        if ( authenticationInfo != null && authenticationInfo.getUserName() != null )
        {
            String password = "";
            if ( authenticationInfo.getPassword() != null )
            {
                password = authenticationInfo.getPassword();
            }
            return new PasswordAuthentication( authenticationInfo.getUserName(), password.toCharArray() );
        }
        return null;
    }

    private Proxy getProxy( ProxyInfo proxyInfo )
    {
        return new Proxy( getProxyType( proxyInfo ), getSocketAddress( proxyInfo ) );
    }

    private Type getProxyType( ProxyInfo proxyInfo )
    {
        if ( ProxyInfo.PROXY_SOCKS4.equals( proxyInfo.getType() ) || ProxyInfo.PROXY_SOCKS5.equals(
            proxyInfo.getType() ) )
        {
            return Type.SOCKS;
        }
        else
        {
            return Type.HTTP;
        }
    }

    public SocketAddress getSocketAddress( ProxyInfo proxyInfo )
    {
        return InetSocketAddress.createUnresolved( proxyInfo.getHost(), proxyInfo.getPort() );
    }

    public void closeConnection()
        throws ConnectionException
    {
        //FIXME WAGON-375 use persistent connection feature provided by the jdk
        if ( putConnection != null )
        {
            putConnection.disconnect();
        }
        authenticator.resetWagon();
    }

    public List<String> getFileList( String destinationDirectory )
        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
    {
        InputData inputData = new InputData();

        if ( destinationDirectory.length() > 0 && !destinationDirectory.endsWith( "/" ) )
        {
            destinationDirectory += "/";
        }

        String url = buildUrl( new Resource( destinationDirectory ) );

        Resource resource = new Resource( destinationDirectory );

        inputData.setResource( resource );

        fillInputData( inputData );

        InputStream is = inputData.getInputStream();

        try
        {

            if ( is == null )
            {
                throw new TransferFailedException(
                    url + " - Could not open input stream for resource: '" + resource + "'" );
            }

            final List<String> htmlFileList = HtmlFileListParser.parseFileList( url, is );
            is.close();
            is = null;
            return htmlFileList;
        }
        catch ( final IOException e )
        {
            throw new TransferFailedException( "Failure transferring " + resource.getName(), e );
        }
        finally
        {
            IOUtils.closeQuietly( is );
        }
    }

    public boolean resourceExists( String resourceName )
        throws TransferFailedException, AuthorizationException
    {
        HttpURLConnection headConnection;

        try
        {
            Resource resource = new Resource( resourceName );
            URL url = new URL( buildUrl( resource ) );
            headConnection = (HttpURLConnection) url.openConnection( this.proxy );

            addHeaders( headConnection );

            headConnection.setRequestMethod( "HEAD" );
            headConnection.setDoOutput( true );

            int statusCode = headConnection.getResponseCode();

            switch ( statusCode )
            {
                case HttpURLConnection.HTTP_OK:
                    return true;

                case HttpURLConnection.HTTP_FORBIDDEN:
                    throw new AuthorizationException( "Access denied to: " + url );

                case HttpURLConnection.HTTP_NOT_FOUND:
                    return false;

                case HttpURLConnection.HTTP_UNAUTHORIZED:
                case HttpURLConnection.HTTP_PROXY_AUTH:
                    throw new AuthorizationException( "Access denied to: " + url );

                default:
                    throw new TransferFailedException(
                        "Failed to look for file: " + buildUrl( resource ) + ". Return code is: " + statusCode );
            }
        }
        catch ( IOException e )
        {
            throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
        }
    }

    public boolean isUseCache()
    {
        return useCache;
    }

    public void setUseCache( boolean useCache )
    {
        this.useCache = useCache;
    }

    public Properties getHttpHeaders()
    {
        return httpHeaders;
    }

    public void setHttpHeaders( Properties httpHeaders )
    {
        this.httpHeaders = httpHeaders;
    }

    void setSystemProperty( String key, String value )
    {
        if ( value != null )
        {
            System.setProperty( key, value );
        }
        else
        {
            System.getProperties().remove( key );
        }
    }

    public void setPreemptiveAuthentication( boolean preemptiveAuthentication )
    {
        this.preemptiveAuthentication = preemptiveAuthentication;
    }

    public LightweightHttpWagonAuthenticator getAuthenticator()
    {
        return authenticator;
    }

    public void setAuthenticator( LightweightHttpWagonAuthenticator authenticator )
    {
        this.authenticator = authenticator;
    }

    /**
     * Convert the IOException that is thrown for most transfer errors that HttpURLConnection encounters to the
     * equivalent {@link TransferFailedException}.
     * <p>
     * Details are extracted from the error stream if possible, either directly or indirectly by way of supporting
     * accessors. The returned exception will include the passed IOException as a cause and a message that is as
     * descriptive as possible.
     *
     * @param originalIOException an IOException thrown from an HttpURLConnection operation
     * @param urlConnection       instance that triggered the IOException
     * @param url                 originating url that triggered the IOException
     * @return exception that is representative of the original cause
     */
    private TransferFailedException convertHttpUrlConnectionException( IOException originalIOException,
                                                                       HttpURLConnection urlConnection,
                                                                       String url )
    {
        // javadoc of HttpUrlConnection, HTTP transfer errors throw IOException
        // In that case, one may attempt to get the status code and reason phrase
        // from the errorstream. We do this, but by way of the following code path
        // getResponseCode()/getResponseMessage() - calls -> getHeaderFields()
        // getHeaderFields() - calls -> getErrorStream()
        try
        {
            // call getResponseMessage first since impl calls getResponseCode as part of that anyways
            String errorResponseMessage = urlConnection.getResponseMessage(); // may be null
            int errorResponseCode = urlConnection.getResponseCode(); // may be -1 if the code cannot be discerned
            String message = formatTransferFailedMessage( url, errorResponseCode, errorResponseMessage,
                    getProxyInfo() );
            return new TransferFailedException( message, originalIOException );

        }
        catch ( IOException errorStreamException )
        {
            // there was a problem using the standard methods, need to fall back to other options
        }

        // Attempt to parse the status code and URL which can be included in an IOException message
        // https://github.com/AdoptOpenJDK/openjdk-jdk11/blame/999dbd4192d0f819cb5224f26e9e7fa75ca6f289/src/java
        // .base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java#L1911L1913
        String ioMsg = originalIOException.getMessage();
        if ( ioMsg != null )
        {
            Matcher matcher = IOEXCEPTION_MESSAGE_PATTERN.matcher( ioMsg );
            if ( matcher.matches() )
            {
                String codeStr = matcher.group( 1 );
                String urlStr = matcher.group( 2 );

                int code = UNKNOWN_STATUS_CODE;
                try
                {
                    code = parseInt( codeStr );
                }
                catch ( NumberFormatException nfe )
                {
                    // if here there is a regex problem
                }

                String message = formatTransferFailedMessage( urlStr, code, null, getProxyInfo() );
                return new TransferFailedException( message, originalIOException );
            }
        }

        String message = formatTransferFailedMessage( url, UNKNOWN_STATUS_CODE, null, getProxyInfo() );
        return new TransferFailedException( message, originalIOException );
    }

}
