package org.apache.maven.plugin.surefire;

/*
 * 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.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
import org.apache.maven.surefire.api.cli.CommandLineOption;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.TestSetFailedException;
import org.apache.maven.surefire.api.util.internal.DumpFileUtils;

import javax.annotation.Nonnull;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

import static java.util.Collections.unmodifiableList;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.apache.maven.surefire.api.booter.DumpErrorSingleton.DUMPSTREAM_FILE_EXT;
import static org.apache.maven.surefire.api.booter.DumpErrorSingleton.DUMP_FILE_EXT;
import static org.apache.maven.surefire.api.cli.CommandLineOption.LOGGING_LEVEL_DEBUG;
import static org.apache.maven.surefire.api.cli.CommandLineOption.LOGGING_LEVEL_ERROR;
import static org.apache.maven.surefire.api.cli.CommandLineOption.LOGGING_LEVEL_INFO;
import static org.apache.maven.surefire.api.cli.CommandLineOption.LOGGING_LEVEL_WARN;
import static org.apache.maven.surefire.api.cli.CommandLineOption.SHOW_ERRORS;

/**
 * Helper class for surefire plugins
 */
public final class SurefireHelper
{
    private static final String DUMP_FILE_DATE = DumpFileUtils.newFormattedDateFileName();

    public static final String DUMP_FILE_PREFIX = DUMP_FILE_DATE + "-jvmRun";

    public static final String DUMP_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMP_FILE_EXT;

    public static final String DUMPSTREAM_FILENAME_FORMATTER = DUMP_FILE_PREFIX + "%d" + DUMPSTREAM_FILE_EXT;

    public static final String DUMPSTREAM_FILENAME = DUMP_FILE_DATE + DUMPSTREAM_FILE_EXT;

    public static final String DUMP_FILENAME = DUMP_FILE_DATE + DUMP_FILE_EXT;

    /**
     * The maximum path that does not require long path prefix on Windows.<br>
     * See {@code sun/nio/fs/WindowsPath} in
     * <a href=
     * "http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/7534523b4174/src/windows/classes/sun/nio/fs/WindowsPath.java#l46">
     * OpenJDK</a>
     * and <a href="https://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath">MSDN article</a>.
     * <br>
     * The maximum path is 260 minus 1 (NUL) but for directories it is 260
     * minus 12 minus 1 (to allow for the creation of a 8.3 file in the directory).
     */
    private static final int MAX_PATH_LENGTH_WINDOWS = 247;

    private static final String[] DUMP_FILES_PRINT =
            {
                    "[date]" + DUMP_FILE_EXT,
                    "[date]-jvmRun[N]" + DUMP_FILE_EXT,
                    "[date]" + DUMPSTREAM_FILE_EXT,
                    "[date]-jvmRun[N]" + DUMPSTREAM_FILE_EXT
            };

    /**
     * The placeholder that is replaced by the executing thread's running number. The thread number
     * range starts with 1
     * Deprecated.
     */
    private static final String THREAD_NUMBER_PLACEHOLDER = "${surefire.threadNumber}";

    /**
     * The placeholder that is replaced by the executing fork's running number. The fork number
     * range starts with 1
     */
    private static final String FORK_NUMBER_PLACEHOLDER = "${surefire.forkNumber}";

    /**
     * Do not instantiate.
     */
    private SurefireHelper()
    {
        throw new IllegalAccessError( "Utility class" );
    }

    @Nonnull
    public static String replaceThreadNumberPlaceholders( @Nonnull String argLine, int threadNumber )
    {
        String threadNumberAsString = String.valueOf( threadNumber );
        return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
                .replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
    }

    public static File replaceForkThreadsInPath( File path, int replacement )
    {
        Deque<String> dirs = new LinkedList<>();
        File root = path;
        while ( !root.exists() )
        {
            dirs.addFirst( replaceThreadNumberPlaceholders( root.getName(), replacement ) );
            root = root.getParentFile();
        }
        File replacedPath = root;
        for ( String dir : dirs )
        {
            replacedPath = new File( replacedPath, dir );
        }
        return replacedPath;
    }

    public static String[] getDumpFilesToPrint()
    {
        return DUMP_FILES_PRINT.clone();
    }

    public static void reportExecution( SurefireReportParameters reportParameters, RunResult result,
                                        PluginConsoleLogger log, Exception firstForkException )
        throws MojoFailureException, MojoExecutionException
    {
        if ( firstForkException == null && !result.isTimeout() && result.isErrorFree() )
        {
            if ( result.getCompletedCount() == 0 && failIfNoTests( reportParameters ) )
            {
                throw new MojoFailureException( "No tests were executed!  "
                                                        + "(Set -DfailIfNoTests=false to ignore this error.)" );
            }
            return;
        }

        if ( reportParameters.isTestFailureIgnore() )
        {
            log.error( createErrorMessage( reportParameters, result, firstForkException ) );
        }
        else
        {
            throwException( reportParameters, result, firstForkException );
        }
    }

    public static List<CommandLineOption> commandLineOptions( MavenSession session, PluginConsoleLogger log )
    {
        List<CommandLineOption> cli = new ArrayList<>();
        if ( log.isErrorEnabled() )
        {
            cli.add( LOGGING_LEVEL_ERROR );
        }

        if ( log.isWarnEnabled() )
        {
            cli.add( LOGGING_LEVEL_WARN );
        }

        if ( log.isInfoEnabled() )
        {
            cli.add( LOGGING_LEVEL_INFO );
        }

        if ( log.isDebugEnabled() )
        {
            cli.add( LOGGING_LEVEL_DEBUG );
        }

        MavenExecutionRequest request = session.getRequest();

        if ( request.isShowErrors() )
        {
            cli.add( SHOW_ERRORS );
        }

        String failureBehavior = request.getReactorFailureBehavior();
        if ( failureBehavior != null )
        {
            try
            {
                cli.add( CommandLineOption.valueOf( failureBehavior ) );
            }
            catch ( IllegalArgumentException e )
            {
                // CommandLineOption does not have specified enum as string. See getRequest() method in Maven Session.
            }
        }

        return unmodifiableList( cli );
    }

    public static void logDebugOrCliShowErrors( String s, PluginConsoleLogger log, Collection<CommandLineOption> cli )
    {
        if ( cli.contains( LOGGING_LEVEL_DEBUG ) )
        {
            log.debug( s );
        }
        else if ( cli.contains( SHOW_ERRORS ) )
        {
            if ( log.isDebugEnabled() )
            {
                log.debug( s );
            }
            else
            {
                log.info( s );
            }
        }
    }

    /**
     * Escape file path for Windows when the path is too long; otherwise returns {@code path}.
     * <br>
     * See <a href=
     * "http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/7534523b4174/src/windows/classes/sun/nio/fs/WindowsPath.java#l46">
     * sun/nio/fs/WindowsPath</a> for "long path" value explanation (=247), and
     * <a href="https://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath">MSDN article</a>
     * for detailed escaping strategy explanation: in short, {@code \\?\} prefix for path with drive letter
     * or {@code \\?\UNC\} for UNC path.
     *
     * @param path    source path
     * @return escaped to platform path
     */
    public static String escapeToPlatformPath( String path )
    {
        if ( IS_OS_WINDOWS && path.length() > MAX_PATH_LENGTH_WINDOWS )
        {
            path = path.startsWith( "\\\\" ) ? "\\\\?\\UNC\\" + path.substring( 2 ) : "\\\\?\\" + path;
        }
        return path;
    }

    private static boolean failIfNoTests( SurefireReportParameters reportParameters )
    {
        return reportParameters.getFailIfNoTests() != null && reportParameters.getFailIfNoTests();
    }

    private static boolean isFatal( Exception firstForkException )
    {
        return firstForkException != null && !( firstForkException instanceof TestSetFailedException );
    }

    private static void throwException( SurefireReportParameters reportParameters, RunResult result,
                                           Exception firstForkException )
            throws MojoFailureException, MojoExecutionException
    {
        if ( isFatal( firstForkException ) || result.isInternalError()  )
        {
            throw new MojoExecutionException( createErrorMessage( reportParameters, result, firstForkException ),
                                                    firstForkException );
        }
        else
        {
            throw new MojoFailureException( createErrorMessage( reportParameters, result, firstForkException ),
                                                  firstForkException );
        }
    }

    private static String createErrorMessage( SurefireReportParameters reportParameters, RunResult result,
                                              Exception firstForkException )
    {
        StringBuilder msg = new StringBuilder( 512 );

        if ( result.isTimeout() )
        {
            msg.append( "There was a timeout in the fork" );
        }
        else
        {
            msg.append( "There are test failures.\n\nPlease refer to " )
                    .append( reportParameters.getReportsDirectory() )
                    .append( " for the individual test results." )
                    .append( '\n' )
                    .append( "Please refer to dump files (if any exist) " )
                    .append( DUMP_FILES_PRINT[0] )
                    .append( ", " )
                    .append( DUMP_FILES_PRINT[1] )
                    .append( " and " )
                    .append( DUMP_FILES_PRINT[2] )
                    .append( "." );
        }

        if ( firstForkException != null && firstForkException.getLocalizedMessage() != null )
        {
            msg.append( '\n' )
                    .append( firstForkException.getLocalizedMessage() );
        }

        if ( result.isFailure() )
        {
            msg.append( '\n' )
                    .append( result.getFailure() );
        }

        return msg.toString();
    }

}
