package org.apache.maven.plugins.linkcheck;

/*
 * 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.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang.SystemUtils;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Profile;
import org.apache.maven.model.Reporting;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationOutputHandler;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.MavenInvocationException;
import org.apache.maven.shared.invoker.PrintStreamHandler;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.cli.CommandLineUtils;

/**
 * @author ltheussl
 * @since 1.1
 */
public class SiteInvoker
{
    private final ArtifactRepository localRepository;

    private final Log log;

    public SiteInvoker( ArtifactRepository localRepository, Log log )
    {
        this.localRepository = localRepository;
        this.log = log;
    }

    /**
     * <p>Invoke Maven for the <code>site</code> phase for a temporary Maven project using
     * <code>tmpReportingOutputDirectory</code> as <code>${project.reporting.outputDirectory}</code>. This is a
     * workaround to be sure that all site files have been correctly generated.
     * </p>
     * <b>Note 1</b>: the Maven Home should be defined in the <code>maven.home</code> Java system property or defined in
     * <code>M2_HOME</code> system env variables. <b>Note 2</b>: we can't use <code>siteOutputDirectory</code> param
     * from site plugin because some plugins <code>${project.reporting.outputDirectory}</code> in their conf.
     *
     * @param project the MavenProject to invoke the site on. Not null.
     * @param tmpReportingOutputDirectory not null
     * @throws IOException if any
     */
    public void invokeSite( MavenProject project, File tmpReportingOutputDirectory )
        throws IOException
    {
        String mavenHome = getMavenHome();
        if ( mavenHome == null || mavenHome.isEmpty() )
        {
            // CHECKSTYLE_OFF: LineLength
            getLog().error( "Could NOT invoke Maven because no Maven Home is defined. "
                + "You need to set the M2_HOME system env variable or a 'maven.home' Java system property." );
            // CHECKSTYLE_ON: LineLength
            return;
        }

        // invoker site parameters
        List<String> goals = Collections.singletonList( "site" );
        Properties properties = new Properties();
        properties.put( "linkcheck.skip", "true" ); // to stop recursion

        File invokerLog =
            FileUtils.createTempFile( "invoker-site-plugin", ".txt", new File( project.getBuild().getDirectory() ) );

        // clone project and set a new reporting output dir
        MavenProject clone;
        try
        {
            clone = (MavenProject) project.clone();
        }
        catch ( CloneNotSupportedException e )
        {
            IOException ioe = new IOException( "CloneNotSupportedException: " + e.getMessage() );
            ioe.setStackTrace( e.getStackTrace() );
            throw ioe;
        }

        // MLINKCHECK-1
        if ( clone.getOriginalModel().getReporting() == null )
        {
            clone.getOriginalModel().setReporting( new Reporting() );
        }

        clone.getOriginalModel().getReporting().setOutputDirectory( tmpReportingOutputDirectory.getAbsolutePath() );
        List<String> profileIds = getActiveProfileIds( clone );

        // create the original model as tmp pom file for the invoker
        File tmpProjectFile = FileUtils.createTempFile( "pom", ".xml", project.getBasedir() );
        
        try ( Writer writer = WriterFactory.newXmlWriter( tmpProjectFile ) )
        {
            clone.writeOriginalModel( writer );
        }

        // invoke it
        try
        {
            invoke( tmpProjectFile, invokerLog, mavenHome, goals, profileIds, properties );
        }
        finally
        {
            if ( !getLog().isDebugEnabled() )
            {
                tmpProjectFile.delete();
            }
        }
    }

    private static List<String> getActiveProfileIds( MavenProject clone )
    {
        List<String> profileIds = new ArrayList<>();

        for ( Object o : clone.getActiveProfiles() )
        {
            profileIds.add( ( (Profile) o ).getId() );
        }

        return profileIds;
    }

    /**
     * @param projectFile not null, should be in the ${project.basedir}
     * @param invokerLog not null
     * @param mavenHome not null
     * @param goals the list of goals
     * @param properties the properties for the invoker
     */
    private void invoke( File projectFile, File invokerLog, String mavenHome, List<String> goals,
                         List<String> activeProfiles, Properties properties )
    {
        Invoker invoker = new DefaultInvoker();
        invoker.setMavenHome( new File( mavenHome ) );
        File localRepoDir = new File( localRepository.getBasedir() );
        invoker.setLocalRepositoryDirectory( localRepoDir );

        InvocationRequest request = new DefaultInvocationRequest();
        request.setLocalRepositoryDirectory( localRepoDir );
        // request.setUserSettingsFile( settingsFile );
        request.setBatchMode( true );
        request.setShowErrors( getLog().isErrorEnabled() );
        request.setDebug( getLog().isDebugEnabled() );
        // request.setShowVersion( false );
        request.setBaseDirectory( projectFile.getParentFile() );
        request.setPomFile( projectFile );
        request.setGoals( goals );
        request.setProperties( properties );
        request.setProfiles( activeProfiles );

        File javaHome = getJavaHome();
        if ( javaHome != null )
        {
            request.setJavaHome( javaHome );
        }

        InvocationResult invocationResult;
        try
        {
            if ( getLog().isDebugEnabled() )
            {
                getLog().debug( "Invoking Maven for the goals: " + goals + " with properties=" + properties );
            }
            invocationResult = invoke( invoker, request, invokerLog, goals, properties, null );
        }
        catch ( MavenInvocationException e )
        {
            getLog().error( "Error when invoking Maven, consult the invoker log." );
            getLog().debug( e );
            return;
        }

        String invokerLogContent = null;
        
        try ( Reader reader = ReaderFactory.newReader( invokerLog, "UTF-8" ) )
        {
            invokerLogContent = IOUtil.toString( reader );
        }
        catch ( IOException e )
        {
            getLog().error( "IOException: " + e.getMessage() );
            getLog().debug( e );
        }

        if ( invokerLogContent != null && invokerLogContent.contains( "Error occurred during initialization of VM" ) )
        {
            getLog().info( "Error occurred during initialization of VM, try to use an empty MAVEN_OPTS." );

            if ( getLog().isDebugEnabled() )
            {
                getLog().debug( "Reinvoking Maven for the goals: " + goals + " with an empty MAVEN_OPTS" );
            }

            try
            {
                invocationResult = invoke( invoker, request, invokerLog, goals, properties, "" );
            }
            catch ( MavenInvocationException e )
            {
                getLog().error( "Error when reinvoking Maven, consult the invoker log." );
                getLog().debug( e );
                return;
            }
        }

        if ( invocationResult.getExitCode() != 0 )
        {
            if ( getLog().isErrorEnabled() )
            {
                getLog().error( "Error when invoking Maven, consult the invoker log file: "
                    + invokerLog.getAbsolutePath() );
            }
        }
    }

    /**
     * @param invoker not null
     * @param request not null
     * @param invokerLog not null
     * @param goals the list of goals
     * @param properties the properties for the invoker
     * @param mavenOpts could be null
     * @return the invocation result
     * @throws MavenInvocationException if any
     */
    private InvocationResult invoke( Invoker invoker, InvocationRequest request, File invokerLog, List<String> goals,
                                     Properties properties, String mavenOpts )
        throws MavenInvocationException
    {
        PrintStream ps;
        OutputStream os = null;
        if ( invokerLog != null )
        {
            if ( getLog().isDebugEnabled() )
            {
                getLog().debug( "Using " + invokerLog.getAbsolutePath() + " to log the invoker" );
            }

            try
            {
                if ( !invokerLog.exists() )
                {
                    invokerLog.getParentFile().mkdirs();
                }
                os = new FileOutputStream( invokerLog );
                ps = new PrintStream( os, true, "UTF-8" );
            }
            catch ( FileNotFoundException e )
            {
                if ( getLog().isErrorEnabled() )
                {
                    getLog().error( "FileNotFoundException: " + e.getMessage()
                        + ". Using System.out to log the invoker." );
                }
                ps = System.out;
            }
            catch ( UnsupportedEncodingException e )
            {
                if ( getLog().isErrorEnabled() )
                {
                    getLog().error( "UnsupportedEncodingException: " + e.getMessage()
                        + ". Using System.out to log the invoker." );
                }
                ps = System.out;
            }
        }
        else
        {
            getLog().debug( "Using System.out to log the invoker." );

            ps = System.out;
        }

        if ( mavenOpts != null )
        {
            request.setMavenOpts( mavenOpts );
        }

        InvocationOutputHandler outputHandler = new PrintStreamHandler( ps, false );
        request.setOutputHandler( outputHandler );
        request.setErrorHandler( outputHandler );

        try
        {
            outputHandler.consumeLine( "Invoking Maven for the goals: " + goals + " with properties=" + properties );
            outputHandler.consumeLine( "" );
            outputHandler.consumeLine( "M2_HOME=" + getMavenHome() );
            outputHandler.consumeLine( "MAVEN_OPTS=" + getMavenOpts() );
            outputHandler.consumeLine( "JAVA_HOME=" + getJavaHome() );
            outputHandler.consumeLine( "JAVA_OPTS=" + getJavaOpts() );
            outputHandler.consumeLine( "" );
        }
        catch ( IOException e )
        {
            throw new MavenInvocationException( e.getMessage(), e.getCause() );
        }

        try
        {
            return invoker.execute( request );
        }
        finally
        {
            IOUtil.close( os );
            ps = null;
        }
    }

    /**
     * @return the Maven home defined in the <code>maven.home</code> system property or defined in <code>M2_HOME</code>
     *         system env variables or null if never setted.
     * @see #invoke(Invoker, InvocationRequest, File, List, Properties, String)
     */
    private String getMavenHome()
    {
        String mavenHome = System.getProperty( "maven.home" );
        if ( mavenHome == null )
        {
            try
            {
                mavenHome = CommandLineUtils.getSystemEnvVars().getProperty( "M2_HOME" );
            }
            catch ( IOException e )
            {
                getLog().error( "IOException: " + e.getMessage() );
                getLog().debug( e );
            }
        }

        File m2Home = new File( mavenHome );
        if ( !m2Home.exists() )
        {
            getLog().error( "Cannot find Maven application directory. Either specify \'maven.home\' "
                + "system property, or M2_HOME environment variable." );
        }

        return mavenHome;
    }

    /**
     * @return the <code>MAVEN_OPTS</code> env variable value or null if not setted.
     * @see #invoke(Invoker, InvocationRequest, File, List, Properties, String)
     */
    private String getMavenOpts()
    {
        String mavenOpts = null;
        try
        {
            mavenOpts = CommandLineUtils.getSystemEnvVars().getProperty( "MAVEN_OPTS" );
        }
        catch ( IOException e )
        {
            getLog().error( "IOException: " + e.getMessage() );
            getLog().debug( e );
        }

        return mavenOpts;
    }

    /**
     * @return the <code>JAVA_HOME</code> from System.getProperty( "java.home" ) By default,
     *         <code>System.getProperty( "java.home" ) = JRE_HOME</code> and <code>JRE_HOME</code> should be in the
     *         <code>JDK_HOME</code> or null if not setted.
     * @see #invoke(Invoker, InvocationRequest, File, List, Properties, String)
     */
    private File getJavaHome()
    {
        File javaHome;
        if ( SystemUtils.IS_OS_MAC_OSX )
        {
            javaHome = SystemUtils.getJavaHome();
        }
        else
        {
            javaHome = new File( SystemUtils.getJavaHome(), ".." );
        }

        if ( javaHome == null || !javaHome.exists() )
        {
            try
            {
                javaHome = new File( CommandLineUtils.getSystemEnvVars().getProperty( "JAVA_HOME" ) );
            }
            catch ( IOException e )
            {
                getLog().error( "IOException: " + e.getMessage() );
                getLog().debug( e );
            }
        }

        if ( javaHome == null || !javaHome.exists() )
        {
            getLog().error( "Cannot find Java application directory. Either specify \'java.home\' "
                + "system property, or JAVA_HOME environment variable." );
        }

        return javaHome;
    }

    /**
     * @return the <code>JAVA_OPTS</code> env variable value or null if not setted.
     * @see #invoke(Invoker, InvocationRequest, File, List, Properties, String)
     */
    private String getJavaOpts()
    {
        String javaOpts = null;
        try
        {
            javaOpts = CommandLineUtils.getSystemEnvVars().getProperty( "JAVA_OPTS" );
        }
        catch ( IOException e )
        {
            getLog().error( "IOException: " + e.getMessage() );
            getLog().debug( e );
        }

        return javaOpts;
    }

    private Log getLog()
    {
        return log;
    }
}
