package org.apache.maven.plugin.compiler;

/*
 * 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.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.maven.api.Artifact;
import org.apache.maven.api.JavaToolchain;
import org.apache.maven.api.Project;
import org.apache.maven.api.Toolchain;
import org.apache.maven.api.plugin.MojoException;
import org.apache.maven.api.plugin.annotations.Component;
import org.apache.maven.api.plugin.annotations.LifecyclePhase;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;
import org.apache.maven.api.plugin.annotations.ResolutionScope;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.ProjectManager;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
import org.codehaus.plexus.languages.java.jpms.LocationManager;
import org.codehaus.plexus.languages.java.jpms.ModuleNameSource;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;

/**
 * Compiles application sources
 *
 * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
 * @since 2.0
 */
@Mojo( name = "compile", defaultPhase = LifecyclePhase.COMPILE,
       requiresDependencyResolution = ResolutionScope.COMPILE )
public class CompilerMojo
    extends AbstractCompilerMojo
{
    /**
     * The source directories containing the sources to be compiled.
     */
    @Parameter( defaultValue = "${project.compileSourceRoots}", readonly = true, required = true )
    private List<String> compileSourceRoots;

    /**
     * The directory for compiled classes.
     */
    @Parameter( defaultValue = "${project.build.outputDirectory}", required = true, readonly = true )
    private File outputDirectory;

    /**
     * Projects main artifact.
     *
     * @todo this is an export variable, really
     */
    @Parameter( defaultValue = "${project.artifact}", readonly = true, required = true )
    private Artifact projectArtifact;

    /**
     * A list of inclusion filters for the compiler.
     */
    @Parameter
    private Set<String> includes = new HashSet<>();

    /**
     * A list of exclusion filters for the compiler.
     */
    @Parameter
    private Set<String> excludes = new HashSet<>();

    /**
     * <p>
     * Specify where to place generated source files created by annotation processing. Only applies to JDK 1.6+
     * </p>
     *
     * @since 2.2
     */
    @Parameter( defaultValue = "${project.build.directory}/generated-sources/annotations" )
    private File generatedSourcesDirectory;

    /**
     * Set this to 'true' to bypass compilation of main sources. Its use is NOT RECOMMENDED, but quite convenient on
     * occasion.
     */
    @Parameter( property = "maven.main.skip" )
    private boolean skipMain;

    @Parameter( defaultValue = "${project.compileClasspathElements}", readonly = true, required = true )
    private List<String> compilePath;

    /**
     * <p>
     * When set to {@code true}, the classes will be placed in <code>META-INF/versions/${release}</code> The release
     * value must be set, otherwise the plugin will fail.
     * </p>
     * <strong>Note: </strong> A jar is only a multirelease jar if <code>META-INF/MANIFEST.MF</code> contains
     * <code>Multi-Release: true</code>. You need to set this by configuring the <a href=
     * "https://maven.apache.org/plugins/maven-jar-plugin/examples/manifest-customization.html">maven-jar-plugin</a>.
     * This implies that you cannot test a multirelease jar using the outputDirectory.
     * 
     * @since 3.7.1
     */
    @Parameter
    private boolean multiReleaseOutput;

    @Component
    private ArtifactManager artifactManager;

    final LocationManager locationManager = new LocationManager();

    private List<String> classpathElements;

    private List<String> modulepathElements;
    
    private Map<String, JavaModuleDescriptor> pathElements;

    protected List<String> getCompileSourceRoots()
    {
        return compileSourceRoots;
    }

    @Override
    protected List<String> getClasspathElements()
    {
        return classpathElements;
    }

    @Override
    protected List<String> getModulepathElements()
    {
        return modulepathElements;
    }

    @Override
    protected Map<String, JavaModuleDescriptor> getPathElements()
    {
        return pathElements;
    }
    
    protected File getOutputDirectory()
    {
        File dir;
        if ( !multiReleaseOutput )
        {
            dir = outputDirectory;
        }
        else
        {
            dir = new File( outputDirectory, "META-INF/versions/" + release );
        }
        return dir;
    }

    public void execute()
        throws MojoException, CompilationFailureException
    {
        if ( skipMain )
        {
            logger.info( "Not compiling main sources" );
            return;
        }
        
        if ( multiReleaseOutput && release == null )
        {
            throw new MojoException( "When using 'multiReleaseOutput' the release must be set" );
        }

        super.execute();

        if ( outputDirectory.isDirectory() )
        {
            artifactManager.setPath( projectArtifact, outputDirectory.toPath() );
        }
    }

    @Override
    protected void preparePaths( Set<File> sourceFiles )
    {
        //assert compilePath != null;

        File moduleDescriptorPath = null;

        boolean hasModuleDescriptor = false;
        for ( File sourceFile : sourceFiles )
        {
            if ( "module-info.java".equals( sourceFile.getName() ) )
            {
                moduleDescriptorPath = sourceFile;
                hasModuleDescriptor = true;
                break;
            }
        }

        if ( hasModuleDescriptor )
        {
            // For now only allow named modules. Once we can create a graph with ASM we can specify exactly the modules
            // and we can detect if auto modules are used. In that case, MavenProject.setFile() should not be used, so
            // you cannot depend on this project and so it won't be distributed.

            modulepathElements = new ArrayList<>( compilePath.size() );
            classpathElements = new ArrayList<>( compilePath.size() );
            pathElements = new LinkedHashMap<>( compilePath.size() );

            ResolvePathsResult<File> resolvePathsResult;
            try
            {
                Collection<File> dependencyArtifacts = getCompileClasspathElements( getProject() );
                
                ResolvePathsRequest<File> request =
                    ResolvePathsRequest.ofFiles( dependencyArtifacts )
                                       .setMainModuleDescriptor( moduleDescriptorPath );
                
                Toolchain toolchain = getToolchain();
                if ( toolchain instanceof JavaToolchain )
                {
                    request.setJdkHome( new File( ( (JavaToolchain) toolchain ).getJavaHome() ) );
                }

                resolvePathsResult = locationManager.resolvePaths( request );
                
                for ( Entry<File, Exception> pathException : resolvePathsResult.getPathExceptions().entrySet() )
                {
                    Throwable cause = pathException.getValue();
                    while ( cause.getCause() != null )
                    {
                        cause = cause.getCause();
                    }
                    String fileName = pathException.getKey().getName();
                    logger.warn( "Can't extract module name from " + fileName + ": " + cause.getMessage() );
                }
                
                JavaModuleDescriptor moduleDescriptor = resolvePathsResult.getMainModuleDescriptor();

                detectFilenameBasedAutomodules( resolvePathsResult, moduleDescriptor );
                
                for ( Map.Entry<File, JavaModuleDescriptor> entry : resolvePathsResult.getPathElements().entrySet() )
                {
                    pathElements.put( entry.getKey().getPath(), entry.getValue() );
                }

                if ( compilerArgs == null )
                {
                    compilerArgs = new ArrayList<>();
                }

                for ( File file : resolvePathsResult.getClasspathElements() )
                {
                    classpathElements.add( file.getPath() );
                    
                    if ( multiReleaseOutput )
                    {
                        if ( getOutputDirectory().toPath().startsWith( file.getPath() ) )
                        {
                            compilerArgs.add( "--patch-module" );
                            compilerArgs.add( String.format( "%s=%s", moduleDescriptor.name(), file.getPath() ) );
                        }
                    }
                }
                
                for ( File file : resolvePathsResult.getModulepathElements().keySet() )
                {
                    modulepathElements.add( file.getPath() );
                }
                
                compilerArgs.add( "--module-version" );
                compilerArgs.add( getProject().getVersion() );
                
            }
            catch ( IOException e )
            {
                logger.warn( e.getMessage() );
            }
        }
        else
        {
            classpathElements = new ArrayList<>();
            for ( File element : getCompileClasspathElements( getProject() ) )
            {
                classpathElements.add( element.getPath() );
            }
            modulepathElements = Collections.emptyList();
        }
    }

    private void detectFilenameBasedAutomodules( final ResolvePathsResult<File> resolvePathsResult,
            final JavaModuleDescriptor moduleDescriptor )
    {
        List<String> automodulesDetected = new ArrayList<>();
        for ( Entry<File, ModuleNameSource> entry : resolvePathsResult.getModulepathElements().entrySet() )
        {
            if ( ModuleNameSource.FILENAME.equals( entry.getValue() ) )
            {
                automodulesDetected.add( entry.getKey().getName() );
            }
        }

        if ( !automodulesDetected.isEmpty() )
        {
            final String message = "Required filename-based automodules detected: "
                    +  automodulesDetected + ". "
                    + "Please don't publish this project to a public artifact repository!";

            if ( moduleDescriptor.exports().isEmpty() )
            {
                // application
                logger.info( message );
            }
            else
            {
                // library
                writeBoxedWarning( message );
            }
        }
    }
    
    private List<File> getCompileClasspathElements( Project project )
    {
        // 3 is outputFolder + 2 preserved for multirelease
        List<Artifact> artifacts = getProjectManager().getResolvedDependencies(
                project, ProjectManager.ResolutionScope.Compile );
        List<File> list = new ArrayList<>( artifacts.size() + 3 );

        if ( multiReleaseOutput )
        {
            File versionsFolder = new File( project.getModel().getBuild().getOutputDirectory(), "META-INF/versions" );
            
            // in reverse order
            for ( int version = Integer.parseInt( getRelease() ) - 1; version >= 9 ; version-- )
            {
                File versionSubFolder = new File( versionsFolder, String.valueOf( version ) );
                if ( versionSubFolder.exists() )
                {
                    list.add( versionSubFolder );
                }
            }
        }

        list.add( new File( project.getModel().getBuild().getOutputDirectory() ) );

        for ( Artifact a : artifacts )
        {
            list.add( a.getPath().get().toFile() );
        }
        return list;
    }
    
    protected SourceInclusionScanner getSourceInclusionScanner( int staleMillis )
    {
        if ( includes.isEmpty() && excludes.isEmpty() )
        {
            return new StaleSourceScanner( staleMillis );
        }

        if ( includes.isEmpty() )
        {
            includes.add( "**/*.java" );
        }

        return new StaleSourceScanner( staleMillis, includes, excludes );
    }

    protected SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding )
    {
        // it's not defined if we get the ending with or without the dot '.'
        String defaultIncludePattern = "**/*" + ( inputFileEnding.startsWith( "." ) ? "" : "." ) + inputFileEnding;

        if ( includes.isEmpty() )
        {
            includes.add( defaultIncludePattern );
        }

        return new SimpleSourceInclusionScanner( includes, excludes );
    }

    protected String getSource()
    {
        return source;
    }

    protected String getTarget()
    {
        return target;
    }

    @Override
    protected String getRelease()
    {
        return release;
    }

    protected String getCompilerArgument()
    {
        return compilerArgument;
    }

    protected Map<String, String> getCompilerArguments()
    {
        return compilerArguments;
    }

    protected File getGeneratedSourcesDirectory()
    {
        return generatedSourcesDirectory;
    }

    private void writeBoxedWarning( String message )
    {
        String line = StringUtils.repeat( "*", message.length() + 4 );
        logger.warn( line );
        logger.warn( "* " + MessageUtils.buffer().strong( message )  + " *" );
        logger.warn( line );
    }
}
