package org.apache.maven.plugins.scmpublish;

/*
 * 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.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.NotFileFilter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.codehaus.plexus.util.MatchPatterns;

/**
 * Publish a content to scm. By default, content is taken from default site staging directory
 * <code>${project.build.directory}/staging</code>.
 * Can be used without project, so usable to update any SCM with any content.
 */
@Mojo ( name = "publish-scm", aggregator = true, requiresProject = false )
public class ScmPublishPublishScmMojo
    extends AbstractScmPublishMojo
{
    /**
     * The content to be published.
     */
    @Parameter ( property = "scmpublish.content", defaultValue = "${project.build.directory}/staging" )
    private File content;

    /**
     */
    @Parameter( defaultValue = "${project}", readonly = true, required = true )
    protected MavenProject project;

    private List<File> deleted = new ArrayList<File>();

    private List<File> added = new ArrayList<File>();

    private List<File> updated = new ArrayList<File>();

    private int directories = 0;
    private int files = 0;
    private long size = 0;

    /**
     * Update scm checkout directory with content.
     *
     * @param checkout        the scm checkout directory
     * @param dir             the content to put in scm (can be <code>null</code>)
     * @param doNotDeleteDirs directory names that should not be deleted from scm even if not in new content:
     *                        used for modules, which content is available only when staging
     * @param baseDir         The base directory of the content
     * @throws IOException
     */
    private void update( File checkout, File dir, List<String> doNotDeleteDirs, File baseDir )
        throws IOException
    {
        String scmSpecificFilename = scmProvider.getScmSpecificFilename();
        String[] files = scmSpecificFilename != null
                        ? checkout.list( new NotFileFilter( new NameFileFilter( scmSpecificFilename ) ) )
                        : checkout.list();

        Path relativeDir = baseDir.toPath( ).toAbsolutePath( ).relativize( dir.toPath( ).toAbsolutePath( ) );
        Set<String> checkoutContent = new HashSet<String>( Arrays.asList( files ) );
        List<String> dirContent = ( dir != null ) ? Arrays.asList( dir.list() ) : Collections.<String>emptyList();

        Set<String> deleted = new HashSet<String>( checkoutContent );
        deleted.removeAll( dirContent );

        MatchPatterns ignoreDeleteMatchPatterns = null;
        List<String> pathsAsList = new ArrayList<String>( 0 );
        if ( ignorePathsToDelete != null && ignorePathsToDelete.length > 0 )
        {
            ignoreDeleteMatchPatterns = MatchPatterns.from( ignorePathsToDelete );
            pathsAsList = Arrays.asList( ignorePathsToDelete );
        }

        for ( String name : deleted )
        {
            String relativeName = relativeDir.resolve( name ).toString( );
            if ( ignoreDeleteMatchPatterns != null && ignoreDeleteMatchPatterns.matches( relativeName, true ) )
            {
                getLog().debug(
                    name + " match one of the patterns '" + pathsAsList + "': do not add to deleted files" );
                continue;
            }
            getLog().debug( "file marked for deletion: " + name );
            File file = new File( checkout, name );

            if ( ( doNotDeleteDirs != null ) && file.isDirectory() && ( doNotDeleteDirs.contains( name ) ) )
            {
                // ignore directory not available
                continue;
            }

            if ( file.isDirectory() )
            {
                update( file, null, null, baseDir );
            }
            this.deleted.add( file );
        }

        for ( String name : dirContent )
        {
            File file = new File( checkout, name );
            File source = new File( dir, name );

            if ( Files.isSymbolicLink( source.toPath() ) )
            {
                if ( !checkoutContent.contains( name ) )
                {
                    this.added.add( file );
                }

                // copy symbolic link (Java 7 only)
                copySymLink( source, file );
            }
            else if ( source.isDirectory() )
            {
                directories++;
                if ( !checkoutContent.contains( name ) )
                {
                    this.added.add( file );
                    file.mkdir();
                }

                update( file, source, null , baseDir );
            }
            else
            {
                if ( checkoutContent.contains( name ) )
                {
                    this.updated.add( file );
                }
                else
                {
                    this.added.add( file );
                }

                copyFile( source, file );
            }
        }
    }

    /**
     * Copy a symbolic link.
     *
     * @param srcFile the source file (expected to be a symbolic link)
     * @param destFile the destination file (which will be a symbolic link)
     * @throws IOException 
     */
    private void copySymLink( File srcFile, File destFile )
        throws IOException
    {
        Files.copy( srcFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING,
                    StandardCopyOption.COPY_ATTRIBUTES, LinkOption.NOFOLLOW_LINKS );
    }

    /**
     * Copy a file content, normalizing newlines when necessary.
     *
     * @param srcFile  the source file
     * @param destFile the destination file
     * @throws IOException
     * @see #requireNormalizeNewlines(File)
     */
    private void copyFile( File srcFile, File destFile )
        throws IOException
    {
        if ( requireNormalizeNewlines( srcFile ) )
        {
            copyAndNormalizeNewlines( srcFile, destFile );
        }
        else
        {
            FileUtils.copyFile( srcFile, destFile );
        }
        files++;
        size += destFile.length();
    }

    /**
     * Copy and normalize newlines.
     *
     * @param srcFile  the source file
     * @param destFile the destination file
     * @throws IOException
     */
    private void copyAndNormalizeNewlines( File srcFile, File destFile )
        throws IOException
    {
        BufferedReader in = null;
        PrintWriter out = null;
        try
        {
            in = new BufferedReader( new InputStreamReader( new FileInputStream( srcFile ), siteOutputEncoding ) );
            out = new PrintWriter( new OutputStreamWriter( new FileOutputStream( destFile ), siteOutputEncoding ) );

            for ( String line = in.readLine(); line != null; line = in.readLine() )
            {
                if ( in.ready() )
                {
                    out.println( line );
                }
                else
                {
                    out.print( line );
                }
            }

            out.close();
            out = null;
            in.close();
            in = null;
        }
        finally
        {
            IOUtils.closeQuietly( out );
            IOUtils.closeQuietly( in );
        }
    }

    public void scmPublishExecute()
        throws MojoExecutionException, MojoFailureException
    {
        if ( siteOutputEncoding == null )
        {
            getLog().warn( "No output encoding, defaulting to UTF-8." );
            siteOutputEncoding = "utf-8";
        }

        if ( !content.exists() )
        {
            throw new MojoExecutionException( "Configured content directory does not exist: " + content );
        }

        if ( !content.canRead() )
        {
            throw new MojoExecutionException( "Can't read content directory: " + content );
        }

        checkoutExisting();

        final File updateDirectory;
        if ( subDirectory == null )
        {
            updateDirectory = checkoutDirectory;
        }
        else
        {
            updateDirectory = new File( checkoutDirectory, subDirectory );

            // Security check for subDirectory with .. inside
            if ( !updateDirectory.toPath().normalize().startsWith( checkoutDirectory.toPath().normalize() ) )
            {
                logError( "Try to acces outside of the checkout directory with sub-directory: %s", subDirectory );
                return;
            }

            if ( !updateDirectory.exists() )
            {
                updateDirectory.mkdirs();
            }

            logInfo( "Will copy content in sub-directory: %s", subDirectory );
        }

        try
        {
            logInfo( "Updating checkout directory with actual content in %s", content );
            update( checkoutDirectory, content, ( project == null ) ? null : project.getModel().getModules(), content );
            String displaySize = org.apache.commons.io.FileUtils.byteCountToDisplaySize( size );
            logInfo( "Content consists of " + MessageUtils.buffer().strong( "%d directories and %d files = %s" ),
                     directories, files, displaySize );
        }
        catch ( IOException ioe )
        {
            throw new MojoExecutionException( "Could not copy content to SCM checkout", ioe );
        }

        logInfo( "Publishing content to SCM will result in "
            + MessageUtils.buffer().strong( "%d addition(s), %d update(s), %d delete(s)" ), added.size(),
                 updated.size(), deleted.size() );

        if ( isDryRun() )
        {
            int pos = checkoutDirectory.getAbsolutePath().length() + 1;
            for ( File addedFile : added )
            {
                logInfo( "- addition %s", addedFile.getAbsolutePath().substring( pos ) );
            }
            for ( File updatedFile : updated )
            {
                logInfo( "- update   %s", updatedFile.getAbsolutePath().substring( pos ) );
            }
            for ( File deletedFile : deleted )
            {
                logInfo( "- delete   %s", deletedFile.getAbsolutePath().substring( pos ) );
            }
            return;
        }

        if ( !added.isEmpty() )
        {
            addFiles( added );
        }

        if ( !deleted.isEmpty() )
        {
            deleteFiles( deleted );
        }

        logInfo( "Checking in SCM, starting at " + new Date() + "..." );
        checkinFiles();
    }
}
