package org.apache.maven.it;

/*
 * 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 junit.framework.TestCase;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.shared.utils.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Jason van Zyl
 * @author Kenney Westerhof
 */
public abstract class AbstractMavenIntegrationTestCase
    extends TestCase
{
    /**
     * Save System.out for progress reports etc.
     */
    private static final PrintStream OUT = System.out;

    /**
     * The format for elapsed time.
     */
    private static final DecimalFormat SECS_FORMAT =
        new DecimalFormat( "(0.0 s)", new DecimalFormatSymbols( Locale.ENGLISH ) );

    /**
     * The zero-based column index where to print the test result.
     */
    private static final int RESULT_COLUMN = 60;

    private boolean skip;

    private BrokenMavenVersionException invert;

    private static ArtifactVersion javaVersion;

    private ArtifactVersion mavenVersion;

    private final VersionRange versionRange;

    private final String matchPattern;

    private static final String DEFAULT_MATCH_PATTERN = "(.*?)-(RC[0-9]+|SNAPSHOT|RC[0-9]+-SNAPSHOT)";

    protected static final String ALL_MAVEN_VERSIONS = "[2.0,)";

    protected AbstractMavenIntegrationTestCase( String versionRangeStr )
    {
        this( versionRangeStr, DEFAULT_MATCH_PATTERN );
    }

    protected AbstractMavenIntegrationTestCase( String versionRangeStr, String matchPattern )
    {
        this.matchPattern = matchPattern;

        try
        {
            versionRange = VersionRange.createFromVersionSpec( versionRangeStr );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw (RuntimeException) new IllegalArgumentException( "Invalid version range: " + versionRangeStr, e );
        }

        ArtifactVersion version = getMavenVersion();
        if ( version != null )
        {
            skip = !versionRange.containsVersion( removePattern( version ) );
        }
        else
        {
            OUT.println( "WARNING: " + getITName() + ": version range '" + versionRange
                             + "' supplied but no Maven version - not skipping test." );
        }
    }

    /**
     * Gets the Java version used to run this test.
     *
     * @return The Java version, never <code>null</code>.
     */
    private ArtifactVersion getJavaVersion()
    {
        if ( javaVersion == null )
        {
            String version = System.getProperty( "java.version" );
            version = version.replaceAll( "[_-]", "." );
            Matcher matcher = Pattern.compile( "(?s).*?(([0-9]+\\.[0-9]+)(\\.[0-9]+)?).*" ).matcher( version );
            if ( matcher.matches() )
            {
                version = matcher.group( 1 );
            }
            javaVersion = new DefaultArtifactVersion( version );
        }
        return javaVersion;
    }

    /**
     * Gets the Maven version used to run this test.
     *
     * @return The Maven version or <code>null</code> if unknown.
     */
    protected final ArtifactVersion getMavenVersion()
    {
        if ( mavenVersion == null )
        {
            String version = System.getProperty( "maven.version", "" );

            if ( version.length() <= 0 || version.startsWith( "${" ) )
            {
                try
                {
                    Verifier verifier = new Verifier( "" );
                    try
                    {
                        version = verifier.getMavenVersion();
                        System.setProperty( "maven.version", version );
                    }
                    finally
                    {
                        verifier.resetStreams();
                    }
                }
                catch ( VerificationException e )
                {
                    e.printStackTrace();
                }
            }

            // NOTE: If the version looks like "${...}" it has been configured from an undefined expression
            if ( version != null && version.length() > 0 && !version.startsWith( "${" ) )
            {
                mavenVersion = new DefaultArtifactVersion( version );
            }
        }
        return mavenVersion;
    }

    /**
     * This allows fine-grained control over execution of individual test methods
     * by allowing tests to adjust to the current Maven version, or else simply avoid
     * executing altogether if the wrong version is present.
     */
    protected boolean matchesVersionRange( String versionRangeStr )
    {
        VersionRange versionRange;
        try
        {
            versionRange = VersionRange.createFromVersionSpec( versionRangeStr );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw (RuntimeException) new IllegalArgumentException( "Invalid version range: " + versionRangeStr, e );
        }

        ArtifactVersion version = getMavenVersion();
        if ( version != null )
        {
            return versionRange.containsVersion( removePattern( version ) );
        }
        else
        {
            OUT.println( "WARNING: " + getITName() + ": version range '" + versionRange
                             + "' supplied but no Maven version found - returning true for match check." );

            return true;
        }
    }

    /**
     * Can be called by version specific setUp calls
     *
     * @return
     */
    protected final boolean isSkipped()
    {
        return skip;
    }

    protected void runTest()
        throws Throwable
    {
        String testName = getTestName();

        if ( testName.startsWith( "mng" ) || Character.isDigit( testName.charAt( 0 ) ) )
        {
            int mng = 4;
            while ( Character.isDigit( testName.charAt( mng ) ) )
            {
                mng++;
            }
            OUT.print( AnsiSupport.bold( testName.substring( 0, mng ) ) );
            OUT.print( ' ' );
            OUT.print( testName.substring( mng ) );
        }
        else
        {
            int index = testName.indexOf( ' ' );
            if ( index == -1 )
            {
                OUT.print( testName );
            }
            else
            {
                OUT.print( AnsiSupport.bold( testName.substring( 0, index ) ) );
                OUT.print( testName.substring( index ) );
            }
            OUT.print( '.' );
        }

        OUT.print( pad( RESULT_COLUMN - testName.length() ) );
        OUT.print( ' ' );

        if ( skip )
        {
            OUT.println( AnsiSupport.warning( "SKIPPED" ) + " - Maven version " + getMavenVersion() + " not in range "
                + versionRange );
            return;
        }

        if ( "true".equals( System.getProperty( "useEmptyLocalRepository", "false" ) ) )
        {
            setupLocalRepo();
        }

        invert = null;
        long milliseconds = System.currentTimeMillis();
        try
        {
            super.runTest();
            milliseconds = System.currentTimeMillis() - milliseconds;
            if ( invert != null )
            {
                throw invert;
            }
            OUT.println( AnsiSupport.success( "OK" ) + " " + formatTime( milliseconds ) );
        }
        catch ( UnsupportedJavaVersionException e )
        {
            OUT.println( AnsiSupport.warning( "SKIPPED" ) + " - Java version " + e.javaVersion + " not in range "
                + e.supportedRange );
            return;
        }
        catch ( UnsupportedMavenVersionException e )
        {
            OUT.println( AnsiSupport.warning( "SKIPPED" ) + " - Maven version " + e.mavenVersion + " not in range "
                + e.supportedRange );
            return;
        }
        catch ( BrokenMavenVersionException e )
        {
            OUT.println( AnsiSupport.error( "UNEXPECTED OK" ) + " - Maven version " + e.mavenVersion
                + " expected to fail " + formatTime( milliseconds ) );
            fail( "Expected failure when with Maven version " + e.mavenVersion );
        }
        catch ( Throwable t )
        {
            milliseconds = System.currentTimeMillis() - milliseconds;
            if ( invert != null )
            {
                OUT.println( AnsiSupport.success( "EXPECTED FAIL" ) + " - Maven version " + invert.mavenVersion
                    + " expected to fail " + formatTime( milliseconds ) );
            }
            else
            {
                OUT.println( AnsiSupport.error( "FAILURE" ) + " " + formatTime( milliseconds ) );
                throw t;
            }
        }
    }

    /**
     * Guards the execution of a test case by checking that the current Java version matches the specified version
     * range. If the check fails, an exception will be thrown which aborts the current test and marks it as skipped. One
     * would usually call this method right at the start of a test method.
     *
     * @param versionRange The version range that specifies the acceptable Java versions for the test, must not be
     *                     <code>null</code>.
     */
    protected void requiresJavaVersion( String versionRange )
    {
        VersionRange range;
        try
        {
            range = VersionRange.createFromVersionSpec( versionRange );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw (RuntimeException) new IllegalArgumentException( "Invalid version range: " + versionRange, e );
        }

        ArtifactVersion version = getJavaVersion();
        if ( !range.containsVersion( version ) )
        {
            throw new UnsupportedJavaVersionException( version, range );
        }
    }

    /**
     * Guards the execution of a test case by checking that the current Maven version matches the specified version
     * range. If the check fails, an exception will be thrown which aborts the current test and marks it as skipped. One
     * would usually call this method right at the start of a test method.
     *
     * @param versionRange The version range that specifies the acceptable Maven versions for the test, must not be
     *                     <code>null</code>.
     */
    protected void requiresMavenVersion( String versionRange )
    {
        VersionRange range;
        try
        {
            range = VersionRange.createFromVersionSpec( versionRange );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw (RuntimeException) new IllegalArgumentException( "Invalid version range: " + versionRange, e );
        }

        ArtifactVersion version = getMavenVersion();
        if ( version != null )
        {
            if ( !range.containsVersion( removePattern( version ) ) )
            {
                throw new UnsupportedMavenVersionException( version, range );
            }
        }
        else
        {
            OUT.println( "WARNING: " + getITName() + ": version range '" + versionRange
                             + "' supplied but no Maven version found - not skipping test." );
        }
    }

    /**
     * Inverts the execution of a test case for cases where we discovered a bug in the test case, have corrected the
     * test case and shipped versions of Maven with a bug because of the faulty test case. This method allows the
     * tests to continue passing against the historical releases as they historically would, as well as verifying that
     * the test is no longer providing a false positive.
     *
     * @param versionRange
     */
    protected void failingMavenVersions( String versionRange )
    {
        assertNull( "Only call failingMavenVersions at most once per test", invert );
        VersionRange range;
        try
        {
            range = VersionRange.createFromVersionSpec( versionRange );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw (RuntimeException) new IllegalArgumentException( "Invalid version range: " + versionRange, e );
        }

        ArtifactVersion version = getMavenVersion();
        if ( version != null )
        {
            if ( range.containsVersion( removePattern( version ) ) )
            {
                invert = new BrokenMavenVersionException( version, range );
            }
        }
        else
        {
            OUT.println( "WARNING: " + getITName() + ": version range '" + versionRange
                             + "' supplied but no Maven version found - not marking test as expected to fail." );
        }
    }

    private class UnsupportedJavaVersionException
        extends RuntimeException
    {
        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public ArtifactVersion javaVersion;

        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public VersionRange supportedRange;

        private UnsupportedJavaVersionException( ArtifactVersion javaVersion, VersionRange supportedRange )
        {
            this.javaVersion = javaVersion;
            this.supportedRange = supportedRange;
        }

    }

    private class UnsupportedMavenVersionException
        extends RuntimeException
    {
        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public ArtifactVersion mavenVersion;

        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public VersionRange supportedRange;

        private UnsupportedMavenVersionException( ArtifactVersion mavenVersion, VersionRange supportedRange )
        {
            this.mavenVersion = mavenVersion;
            this.supportedRange = supportedRange;
        }

    }

    private class BrokenMavenVersionException
        extends RuntimeException
    {
        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public ArtifactVersion mavenVersion;

        @SuppressWarnings( "checkstyle:visibilitymodifier" )
        public VersionRange supportedRange;

        private BrokenMavenVersionException( ArtifactVersion mavenVersion, VersionRange supportedRange )
        {
            this.mavenVersion = mavenVersion;
            this.supportedRange = supportedRange;
        }

    }

    private String getITName()
    {
        String simpleName = getClass().getName();
        int idx = simpleName.lastIndexOf( '.' );
        simpleName = idx >= 0 ? simpleName.substring( idx + 1 ) : simpleName;
        simpleName = simpleName.startsWith( "MavenIT" ) ? simpleName.substring( "MavenIT".length() ) : simpleName;
        simpleName = simpleName.endsWith( "Test" ) ? simpleName.substring( 0, simpleName.length() - 4 ) : simpleName;
        return simpleName;
    }

    private String getTestName()
    {
        String className = getITName();
        String methodName = getName();
        if ( methodName.startsWith( "test" ) )
        {
            methodName = methodName.substring( 4 );
        }
        return className + '.' + methodName + "()";
    }

    private String pad( int chars )
    {
        StringBuilder buffer = new StringBuilder( 128 );
        for ( int i = 0; i < chars; i++ )
        {
            buffer.append( '.' );
        }
        return buffer.toString();
    }

    private String formatTime( long milliseconds )
    {
        return SECS_FORMAT.format( milliseconds / 1000.0 );
    }

    protected File setupLocalRepo()
        throws IOException
    {
        String tempDirPath = System.getProperty( "maven.it.tmpdir", System.getProperty( "java.io.tmpdir" ) );
        File localRepo = new File( tempDirPath, "local-repository/" + getITName() );
        if ( localRepo.isDirectory() )
        {
            FileUtils.deleteDirectory( localRepo );
        }

        System.setProperty( "maven.repo.local", localRepo.getAbsolutePath() );

        return localRepo;
    }

    ArtifactVersion removePattern( ArtifactVersion version )
    {
        String v = version.toString();

        Matcher m = Pattern.compile( matchPattern ).matcher( v );

        if ( m.matches() )
        {
            return new DefaultArtifactVersion( m.group( 1 ) );
        }
        return version;
    }

    protected Verifier newVerifier( String basedir )
        throws VerificationException
    {
        return newVerifier( basedir, false );
    }

    protected Verifier newVerifier( String basedir, String settings )
        throws VerificationException
    {
        return newVerifier( basedir, settings, false );
    }

    protected Verifier newVerifier( String basedir, boolean debug )
        throws VerificationException
    {
        return newVerifier( basedir, "", debug );
    }

    protected Verifier newVerifier( String basedir, String settings, boolean debug )
        throws VerificationException
    {
        Verifier verifier = new Verifier( basedir, debug );

        verifier.setAutoclean( false );

        if ( settings != null )
        {
            File settingsFile;
            if ( settings.length() > 0 )
            {
                settingsFile = new File( "settings-" + settings + ".xml" );
            }
            else
            {
                settingsFile = new File( "settings.xml" );
            }

            if ( !settingsFile.isAbsolute() )
            {
                String settingsDir = System.getProperty( "maven.it.global-settings.dir", "" );
                if ( settingsDir.length() > 0 )
                {
                    settingsFile = new File( settingsDir, settingsFile.getPath() );
                }
                else
                {
                    //
                    // Make is easier to run ITs from m2e in Maven IT mode without having to set any additional
                    // properties.
                    //
                    settingsFile = new File( "target/test-classes", settingsFile.getPath() );
                }
            }

            String path = settingsFile.getAbsolutePath();

            // dedicated CLI option only available since MNG-3914
            if ( matchesVersionRange( "[2.1.0,)" ) )
            {
                verifier.getCliOptions().add( "--global-settings" );
                if ( path.indexOf( ' ' ) < 0 )
                {
                    verifier.getCliOptions().add( path );
                }
                else
                {
                    verifier.getCliOptions().add( '"' + path + '"' );
                }
            }
            else
            {
                verifier.getSystemProperties().put( "org.apache.maven.global-settings", path );
            }
        }

        if ( matchesVersionRange( "(3.2.5,)" ) )
        {
            String multiModuleProjectDirectory = findMultiModuleProjectDirectory( basedir );
            verifier.getSystemProperties().put( "maven.multiModuleProjectDirectory", multiModuleProjectDirectory );
        }

        try
        {
            // auto set source+target to lowest reasonable java version
            // Java9 requires at least 1.6
            if ( VersionRange.createFromVersionSpec( "[9,12)" ).containsVersion( getJavaVersion() ) )
            {
                verifier.getSystemProperties().put( "maven.compiler.source", "1.7" );
                verifier.getSystemProperties().put( "maven.compiler.target", "1.7" );
                verifier.getSystemProperties().put( "maven.compiler.release", "7" );
            }
            // Java12 requires at least 7
            if ( VersionRange.createFromVersionSpec( "[12,)" ).containsVersion( getJavaVersion() ) )
            {
                verifier.getSystemProperties().put( "maven.compiler.source", "7" );
                verifier.getSystemProperties().put( "maven.compiler.target", "7" );
                verifier.getSystemProperties().put( "maven.compiler.release", "7" );
            }
        }
        catch ( InvalidVersionSpecificationException e )
        {
            // noop
        }

        return verifier;
    }

    private boolean hasDotMvnSubDirectory( Path path )
    {
        final Path probablySubDirectory = path.resolve( ".mvn" );
        return Files.exists( probablySubDirectory ) && Files.isDirectory( probablySubDirectory );
    }

    private String findMultiModuleProjectDirectory( String basedir )
    {
        Path path = Paths.get( basedir );
        Path result = path;

        Collection<Path> fileSystemRoots = new ArrayList<>();
        for ( Path root : path.getFileSystem().getRootDirectories() )
        {
            fileSystemRoots.add( root );
        }

        while ( !fileSystemRoots.contains( path ) )
        {
            if ( hasDotMvnSubDirectory( path ) )
            {
                result = path;
                break;
            }
            path = path.getParent();
        }

        return result.toString();
    }

    public static void assertCanonicalFileEquals( String message, File expected, File actual )
        throws IOException
    {
        assertEquals( message, expected.getCanonicalFile(), actual.getCanonicalFile() );
    }

    public static void assertCanonicalFileEquals( File expected, File actual )
        throws IOException
    {
        assertCanonicalFileEquals( null, expected, actual );
    }

    public static void assertCanonicalFileEquals( String message, String expected, String actual )
        throws IOException
    {
        assertCanonicalFileEquals( message, new File( expected ), new File( actual ) );
    }

    public static void assertCanonicalFileEquals( String expected, String actual )
        throws IOException
    {
        assertCanonicalFileEquals( null, new File( expected ), new File( actual ) );
    }
}
