package org.apache.maven.index.cli;

/*
 * 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.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.lucene.store.FSDirectory;
import org.apache.maven.index.ArtifactContext;
import org.apache.maven.index.ArtifactInfo;
import org.apache.maven.index.ArtifactScanningListener;
import org.apache.maven.index.NexusIndexer;
import org.apache.maven.index.ScanningResult;
import org.apache.maven.index.context.IndexCreator;
import org.apache.maven.index.context.IndexingContext;
import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
import org.apache.maven.index.packer.IndexPacker;
import org.apache.maven.index.packer.IndexPackingRequest;
import org.apache.maven.index.packer.IndexPackingRequest.IndexFormat;
import org.apache.maven.index.updater.DefaultIndexUpdater;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LoggerManager;
import org.codehaus.plexus.tools.cli.AbstractCli;
import org.codehaus.plexus.util.IOUtil;

/**
 * A command line tool that can be used to index local Maven repository.
 * <p/>
 * The following command line options are supported:
 * <ul>
 * <li>-repository <path> : required path to repository to be indexed</li>
 * <li>-index <path> : required index folder used to store created index or where previously created index is stored</li>
 * <li>-name <path> : required repository name/id</li>
 * <li>-target <path> : optional folder name where to save produced index files</li>
 * <li>-type <path> : optional indexer types</li>
 * <li>-format <path> : optional indexer formats</li>
 * </ul>
 * When index folder contains previously created index, the tool will use it as a base line and will generate chunks for
 * the incremental updates.
 * <p/>
 * The indexer types could be one of default, min or full. You can also specify list of comma-separated custom index
 * creators. An index creator should be a regular Plexus component, see
 * {@link org.apache.maven.index.creator.MinimalArtifactInfoIndexCreator} and
 * {@link org.apache.maven.index.creator.JarFileContentsIndexCreator}.
 */
public class NexusIndexerCli
    extends AbstractCli
{
    // Command line options

    public static final char REPO = 'r';

    public static final char INDEX = 'i';

    public static final char NAME = 'n';

    public static final char TYPE = 't';

    public static final char TARGET_DIR = 'd';

    public static final char CREATE_INCREMENTAL_CHUNKS = 'c';

    public static final char CREATE_FILE_CHECKSUMS = 's';

    public static final char INCREMENTAL_CHUNK_KEEP_COUNT = 'k';

    public static final char LEGACY = 'l';

    public static final char UNPACK = 'u';

    private static final long MB = 1024 * 1024;

    private Options options;

    private int status = 0;

    public static void main( String[] args )
        throws Exception
    {
        NexusIndexerCli cli = new NexusIndexerCli();

        cli.execute( args );

        System.exit( cli.status );
    }

    @Override
    public int execute( String[] arg0, ClassWorld arg1 )
    {
        int value = super.execute( arg0, arg1 );

        if ( status == 0 )
        {
            status = value;
        }

        return status;
    }

    @Override
    public int execute( String[] args )
    {
        int value = super.execute( args );

        if ( status == 0 )
        {
            status = value;
        }

        return status;
    }

    @Override
    protected void showError( String message, Exception e, boolean show )
    {
        status = 1;
        super.showError( message, e, show );
    }

    @Override
    protected int showFatalError( String message, Exception e, boolean show )
    {
        status = 1;
        return super.showFatalError( message, e, show );
    }

    @Override
    public CommandLine parse( String[] args )
        throws ParseException
    {
        try
        {
            return super.parse( args );
        }
        catch ( ParseException e )
        {
            status = 1;
            throw e;
        }
    }

    @Override
    public String getPomPropertiesPath()
    {
        return "META-INF/maven/org.sonatype.nexus/nexus-indexer/pom.properties";
    }

    @Override
    @SuppressWarnings( "static-access" )
    public Options buildCliOptions( Options options )
    {
        this.options = options;

        options.addOption( OptionBuilder.withLongOpt( "index" ).hasArg() //
        .withDescription( "Path to the index folder." ).create( INDEX ) );

        options.addOption( OptionBuilder.withLongOpt( "destination" ).hasArg() //
        .withDescription( "Target folder." ).create( TARGET_DIR ) );

        options.addOption( OptionBuilder.withLongOpt( "repository" ).hasArg() //
        .withDescription( "Path to the Maven repository." ).create( REPO ) );

        options.addOption( OptionBuilder.withLongOpt( "name" ).hasArg() //
        .withDescription( "Repository name." ).create( NAME ) );

        options.addOption( OptionBuilder.withLongOpt( "chunks" ) //
        .withDescription( "Create incremental chunks." ).create( CREATE_INCREMENTAL_CHUNKS ) );

        options.addOption( OptionBuilder.withLongOpt( "keep" ).hasArg().withDescription(
            "Number of incremental chunks to keep." ).create( INCREMENTAL_CHUNK_KEEP_COUNT ) );

        options.addOption( OptionBuilder.withLongOpt( "checksums" ) //
        .withDescription( "Create checksums for all files (sha1, md5)." ).create( CREATE_FILE_CHECKSUMS ) );

        options.addOption( OptionBuilder.withLongOpt( "type" ).hasArg() //
        .withDescription( "Indexer type (default, min, full or coma separated list of custom types)." ).create( TYPE ) );

        options.addOption( OptionBuilder.withLongOpt( "legacy" ) //
        .withDescription( "Build legacy .zip index file" ).create( LEGACY ) );

        options.addOption( OptionBuilder.withLongOpt( "unpack" ) //
        .withDescription( "Unpack an index file" ).create( UNPACK ) );

        return options;
    }

    @Override
    public void displayHelp()
    {
        System.out.println();

        HelpFormatter formatter = new HelpFormatter();

        formatter.printHelp( "nexus-indexer [options]", "\nOptions:", options, "\n" );
    }

    public void displayHelp( String message )
    {
        System.out.println();

        System.out.println( message );

        System.out.println();

        displayHelp();
    }

    @Override
    public void invokePlexusComponent( final CommandLine cli, PlexusContainer plexus )
        throws Exception
    {
        final DefaultContainerConfiguration configuration = new DefaultContainerConfiguration();
        configuration.setClassWorld( ( (DefaultPlexusContainer) plexus ).getClassWorld() );
        configuration.setClassPathScanning( PlexusConstants.SCANNING_INDEX );

        // replace plexus, as PlexusCli is blunt, does not allow to modify configuration
        // TODO: get rid of PlexusCli use!
        plexus = new DefaultPlexusContainer( configuration );

        if ( cli.hasOption( QUIET ) )
        {
            setLogLevel( plexus, Logger.LEVEL_DISABLED );
        }
        else if ( cli.hasOption( DEBUG ) )
        {
            setLogLevel( plexus, Logger.LEVEL_DEBUG );
        }
        else if ( cli.hasOption( ERRORS ) )
        {
            setLogLevel( plexus, Logger.LEVEL_ERROR );
        }

        if ( cli.hasOption( UNPACK ) )
        {
            unpack( cli, plexus );
        }
        else if ( cli.hasOption( INDEX ) && cli.hasOption( REPO ) )
        {
            index( cli, plexus );
        }
        else
        {
            status = 1;

            displayHelp( "Use either unpack (\"" + UNPACK + "\") or index (\"" + INDEX + "\" and \"" + REPO
                + "\") options, but none has been found!" );
        }
    }

    private void setLogLevel( PlexusContainer plexus, int logLevel )
        throws ComponentLookupException
    {
        plexus.lookup( LoggerManager.class ).setThresholds( logLevel );
    }

    private void index( final CommandLine cli, PlexusContainer plexus )
        throws ComponentLookupException, IOException, UnsupportedExistingLuceneIndexException
    {
        String indexDirectoryName = cli.getOptionValue( INDEX );

        File indexFolder = new File( indexDirectoryName );

        String outputDirectoryName = cli.getOptionValue( TARGET_DIR, "." );

        File outputFolder = new File( outputDirectoryName );

        File repositoryFolder = new File( cli.getOptionValue( REPO ) );

        String repositoryName = cli.getOptionValue( NAME, indexFolder.getName() );

        List<IndexCreator> indexers = getIndexers( cli, plexus );

        boolean createChecksums = cli.hasOption( CREATE_FILE_CHECKSUMS );

        boolean createIncrementalChunks = cli.hasOption( CREATE_INCREMENTAL_CHUNKS );

        boolean createLegacyIndex = cli.hasOption( LEGACY );

        boolean debug = cli.hasOption( DEBUG );

        boolean quiet = cli.hasOption( QUIET );

        Integer chunkCount =
            cli.hasOption( INCREMENTAL_CHUNK_KEEP_COUNT ) ? Integer.parseInt( cli.getOptionValue( INCREMENTAL_CHUNK_KEEP_COUNT ) )
                : null;

        if ( !quiet )
        {
            System.err.printf( "Repository Folder: %s\n", repositoryFolder.getAbsolutePath() );
            System.err.printf( "Index Folder:      %s\n", indexFolder.getAbsolutePath() );
            System.err.printf( "Output Folder:     %s\n", outputFolder.getAbsolutePath() );
            System.err.printf( "Repository name:   %s\n", repositoryName );
            System.err.printf( "Indexers: %s\n", indexers.toString() );

            if ( createChecksums )
            {
                System.err.printf( "Will create checksum files for all published files (sha1, md5).\n" );
            }
            else
            {
                System.err.printf( "Will not create checksum files.\n" );
            }

            if ( createIncrementalChunks )
            {
                System.err.printf( "Will create incremental chunks for changes, along with baseline file.\n" );
            }
            else
            {
                System.err.printf( "Will create baseline file.\n" );
            }

            if ( createLegacyIndex )
            {
                System.err.printf( "Will also create legacy .zip index file.\n" );
            }
        }

        NexusIndexer indexer = plexus.lookup( NexusIndexer.class );

        long tstart = System.currentTimeMillis();

        IndexingContext context = indexer.addIndexingContext( //
            repositoryName, // context id
            repositoryName, // repository id
            repositoryFolder, // repository folder
            indexFolder, // index folder
            null, // repositoryUrl
            null, // index update url
            indexers );

        try
        {
            IndexPacker packer = plexus.lookup( IndexPacker.class );

            ArtifactScanningListener listener = new IndexerListener( context, debug, quiet );

            indexer.scan( context, listener, true );

            IndexPackingRequest request = new IndexPackingRequest( context, outputFolder );

            request.setCreateChecksumFiles( createChecksums );

            request.setCreateIncrementalChunks( createIncrementalChunks );

            if ( createLegacyIndex )
            {
                request.setFormats( Arrays.asList( IndexFormat.FORMAT_LEGACY, IndexFormat.FORMAT_V1 ) );
            }
            else
            {
                request.setFormats( Arrays.asList( IndexFormat.FORMAT_V1 ) );
            }

            if ( chunkCount != null )
            {
                request.setMaxIndexChunks( chunkCount.intValue() );
            }

            packIndex( packer, request, debug, quiet );

            if ( !quiet )
            {
                printStats( tstart );
            }
        }
        finally
        {
            indexer.removeIndexingContext( context, false );
        }
    }

    private void unpack( CommandLine cli, PlexusContainer plexus )
        throws ComponentLookupException, IOException
    {
        final String indexDirectoryName = cli.getOptionValue( INDEX, "." );
        final File indexFolder = new File( indexDirectoryName ).getCanonicalFile();
        final File indexArchive = new File( indexFolder, IndexingContext.INDEX_FILE_PREFIX + ".gz" );

        final String outputDirectoryName = cli.getOptionValue( TARGET_DIR, "." );
        final File outputFolder = new File( outputDirectoryName ).getCanonicalFile();

        final boolean quiet = cli.hasOption( QUIET );
        if ( !quiet )
        {
            System.err.printf( "Index Folder:      %s\n", indexFolder.getAbsolutePath() );
            System.err.printf( "Output Folder:     %s\n", outputFolder.getAbsolutePath() );
        }

        long tstart = System.currentTimeMillis();

        final FSDirectory directory = FSDirectory.open( outputFolder );

        final List<IndexCreator> indexers = getIndexers( cli, plexus );

        BufferedInputStream is = null;
        try
        {
            is = new BufferedInputStream( new FileInputStream( indexArchive ) );
            DefaultIndexUpdater.unpackIndexData( is, directory, (IndexingContext) Proxy.newProxyInstance(
                getClass().getClassLoader(), new Class[] { IndexingContext.class }, new PartialImplementation()
                {
                    public List<IndexCreator> getIndexCreators()
                    {
                        return indexers;
                    }
                } )

            );
        }
        finally
        {
            IOUtil.close( is );
            if ( directory != null )
            {
                directory.close();
            }
        }

        if ( !quiet )
        {
            printStats( tstart );
        }
    }

    private List<IndexCreator> getIndexers( final CommandLine cli, PlexusContainer plexus )
        throws ComponentLookupException
    {
        String type = "default";

        if ( cli.hasOption( TYPE ) )
        {
            type = cli.getOptionValue( TYPE );
        }

        List<IndexCreator> indexers = new ArrayList<IndexCreator>(); // NexusIndexer.DEFAULT_INDEX;

        if ( "default".equals( type ) )
        {
            indexers.add( plexus.lookup( IndexCreator.class, "min" ) );
            indexers.add( plexus.lookup( IndexCreator.class, "jarContent" ) );
        }
        else if ( "full".equals( type ) )
        {
            for ( Object component : plexus.lookupList( IndexCreator.class ) )
            {
                indexers.add( (IndexCreator) component );
            }
        }
        else
        {
            for ( String hint : type.split( "," ) )
            {
                indexers.add( plexus.lookup( IndexCreator.class, hint ) );
            }
        }
        return indexers;
    }

    private void packIndex( IndexPacker packer, IndexPackingRequest request, boolean debug, boolean quiet )
    {
        try
        {
            packer.packIndex( request );
        }
        catch ( IOException e )
        {
            if ( !quiet )
            {
                System.err.printf( "Cannot zip index; \n", e.getMessage() );

                if ( debug )
                {
                    e.printStackTrace();
                }
            }
        }
    }

    private void printStats( final long startTimeInMillis )
    {
        long t = System.currentTimeMillis() - startTimeInMillis;

        long s = t / 1000L;
        if ( t > 60 * 1000 )
        {
            long m = t / 1000L / 60L;

            System.err.printf( "Total time:   %d min %d sec\n", m, s - ( m * 60 ) );
        }
        else
        {
            System.err.printf( "Total time:   %d sec\n", s );
        }

        Runtime r = Runtime.getRuntime();

        System.err.printf( "Final memory: %dM/%dM\n", //
            ( r.totalMemory() - r.freeMemory() ) / MB, r.totalMemory() / MB );
    }

    /**
     * Scanner listener
     */
    private static final class IndexerListener
        implements ArtifactScanningListener
    {
        private final IndexingContext context;

        private final boolean debug;

        private boolean quiet;

        private long ts = System.currentTimeMillis();

        private int count;

        IndexerListener( IndexingContext context, boolean debug, boolean quiet )
        {
            this.context = context;
            this.debug = debug;
            this.quiet = quiet;
        }

        public void scanningStarted( IndexingContext context )
        {
            if ( !quiet )
            {
                System.err.println( "Scanning started" );
            }
        }

        public void artifactDiscovered( ArtifactContext ac )
        {
            count++;

            long t = System.currentTimeMillis();

            ArtifactInfo ai = ac.getArtifactInfo();

            if ( !quiet && debug && "maven-plugin".equals( ai.packaging ) )
            {
                System.err.printf( "Plugin: %s:%s:%s - %s %s\n", //
                    ai.groupId, ai.artifactId, ai.version, ai.prefix, "" + ai.goals );
            }

            if ( !quiet && ( debug || ( t - ts ) > 2000L ) )
            {
                System.err.printf( "  %6d %s\n", count, formatFile( ac.getPom() ) );
                ts = t;
            }
        }

        public void artifactError( ArtifactContext ac, Exception e )
        {
            if ( !quiet )
            {
                System.err.printf( "! %6d %s - %s\n", count, formatFile( ac.getPom() ), e.getMessage() );

                System.err.printf( "         %s\n", formatFile( ac.getArtifact() ) );

                if ( debug )
                {
                    e.printStackTrace();
                }
            }

            ts = System.currentTimeMillis();
        }

        private String formatFile( File file )
        {
            return file.getAbsolutePath().substring( context.getRepository().getAbsolutePath().length() + 1 );
        }

        public void scanningFinished( IndexingContext context, ScanningResult result )
        {
            if ( !quiet )
            {
                if ( result.hasExceptions() )
                {
                    System.err.printf( "Scanning errors:   %s\n", result.getExceptions().size() );
                }

                System.err.printf( "Artifacts added:   %s\n", result.getTotalFiles() );
                System.err.printf( "Artifacts deleted: %s\n", result.getDeletedFiles() );
            }
        }
    }

}
