/*
 * 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.
 */
package org.apache.maven.shared.invoker;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.maven.shared.invoker.InvocationRequest.CheckSumPolicy;
import org.apache.maven.shared.invoker.InvocationRequest.ReactorFailureBehavior;
import org.apache.maven.shared.utils.Os;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.apache.maven.shared.utils.cli.Commandline;

/**
 * <p>MavenCommandLineBuilder class.</p>
 */
public class MavenCommandLineBuilder {

    private static final InvokerLogger DEFAULT_LOGGER = new SystemOutLogger();

    private InvokerLogger logger = DEFAULT_LOGGER;

    private File baseDirectory;

    private File localRepositoryDirectory;

    private File mavenHome;

    private File mavenExecutable;

    /**
     * <p>build.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @return a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     * @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
     */
    public Commandline build(InvocationRequest request) throws CommandLineConfigurationException {

        Commandline cli = new Commandline();

        setupMavenHome(request);

        // discover value for working directory
        setupBaseDirectory(request);
        cli.setWorkingDirectory(baseDirectory);

        checkRequiredState();

        setupMavenExecutable(request);
        cli.setExecutable(mavenExecutable.getAbsolutePath());

        // handling for OS-level envars
        setShellEnvironment(request, cli);

        // interactive, offline, update-snapshots,
        // debug/show-errors, checksum policy
        setFlags(request, cli);

        // failure behavior and [eventually] forced-reactor
        // includes/excludes, etc.
        setReactorBehavior(request, cli);

        // local repository location
        setLocalRepository(request, cli);

        // pom-file handling
        setPomLocation(request, cli);

        setSettingsLocation(request, cli);

        setToolchainsLocation(request, cli);

        setProperties(request, cli);

        setProfiles(request, cli);

        setGoals(request, cli);

        setThreads(request, cli);

        setArgs(request, cli);

        return cli;
    }

    /**
     * <p>checkRequiredState.</p>
     */
    protected void checkRequiredState() {
        if (logger == null) {
            throw new IllegalStateException("A logger instance is required.");
        }
    }

    /**
     * <p>setSettingsLocation.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setSettingsLocation(InvocationRequest request, Commandline cli) {
        File userSettingsFile = request.getUserSettingsFile();

        if (userSettingsFile != null) {
            try {
                userSettingsFile = userSettingsFile.getCanonicalFile();
            } catch (IOException e) {
                logger.debug(
                        "Failed to canonicalize user settings path: " + userSettingsFile.getAbsolutePath()
                                + ". Using as-is.",
                        e);
            }

            cli.createArg().setValue("-s");
            cli.createArg().setValue(userSettingsFile.getPath());
        }

        File globalSettingsFile = request.getGlobalSettingsFile();

        if (globalSettingsFile != null) {
            try {
                globalSettingsFile = globalSettingsFile.getCanonicalFile();
            } catch (IOException e) {
                logger.debug(
                        "Failed to canonicalize global settings path: " + globalSettingsFile.getAbsolutePath()
                                + ". Using as-is.",
                        e);
            }

            cli.createArg().setValue("-gs");
            cli.createArg().setValue(globalSettingsFile.getPath());
        }
    }

    /**
     * <p>setToolchainsLocation.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setToolchainsLocation(InvocationRequest request, Commandline cli) {
        File toolchainsFile = request.getToolchainsFile();

        if (toolchainsFile != null) {
            try {
                toolchainsFile = toolchainsFile.getCanonicalFile();
            } catch (IOException e) {
                logger.debug(
                        "Failed to canonicalize toolchains path: " + toolchainsFile.getAbsolutePath()
                                + ". Using as-is.",
                        e);
            }

            cli.createArg().setValue("-t");
            cli.createArg().setValue(toolchainsFile.getPath());
        }
    }

    /**
     * <p>setShellEnvironment.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setShellEnvironment(InvocationRequest request, Commandline cli) {
        if (request.isShellEnvironmentInherited()) {
            cli.addSystemEnvironment();
        }

        if (request.getJavaHome() != null) {
            cli.addEnvironment("JAVA_HOME", request.getJavaHome().getAbsolutePath());
        }

        if (request.getMavenOpts() != null) {
            cli.addEnvironment("MAVEN_OPTS", request.getMavenOpts());
        }

        for (Map.Entry<String, String> entry : request.getShellEnvironments().entrySet()) {
            cli.addEnvironment(entry.getKey(), entry.getValue());
        }
    }

    /**
     * <p>setProfiles.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setProfiles(InvocationRequest request, Commandline cli) {
        List<String> profiles = request.getProfiles();

        if ((profiles != null) && !profiles.isEmpty()) {
            cli.createArg().setValue("-P");
            cli.createArg().setValue(StringUtils.join(profiles.iterator(), ","));
        }
    }

    /**
     * <p>setGoals.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     * @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
     */
    protected void setGoals(InvocationRequest request, Commandline cli) throws CommandLineConfigurationException {
        List<String> goals = request.getGoals();

        if ((goals != null) && !goals.isEmpty()) {
            try {
                cli.createArg().setLine(StringUtils.join(goals.iterator(), " "));
            } catch (CommandLineException e) {
                throw new CommandLineConfigurationException("Problem setting goals", e);
            }
        }
    }

    /**
     * <p>setProperties.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setProperties(InvocationRequest request, Commandline cli) {
        Properties properties = request.getProperties();

        if (properties != null) {
            for (Entry<Object, Object> entry : properties.entrySet()) {
                String key = (String) entry.getKey();
                String value = (String) entry.getValue();

                cli.createArg().setValue("-D");
                cli.createArg().setValue(key + '=' + value);
            }
        }
    }

    /**
     * <p>setPomLocation.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setPomLocation(InvocationRequest request, Commandline cli) {
        File pom = request.getPomFile();
        String pomFilename = request.getPomFileName();

        if (pom == null) {
            if (pomFilename != null) {
                pom = new File(baseDirectory, pomFilename);
            } else {
                pom = new File(baseDirectory, "pom.xml");
            }
        }

        try {
            pom = pom.getCanonicalFile();
        } catch (IOException e) {
            logger.debug("Failed to canonicalize the POM path: " + pom + ". Using as-is.", e);
        }

        if (pom.getParentFile().equals(baseDirectory)) {
            // pom in project workspace
            if (!"pom.xml".equals(pom.getName())) {
                logger.debug("Specified POM file is not named 'pom.xml'. "
                        + "Using the '-f' command-line option to accommodate non-standard filename...");

                cli.createArg().setValue("-f");
                cli.createArg().setValue(pom.getName());
            }
        } else {
            cli.createArg().setValue("-f");
            cli.createArg().setValue(pom.getPath());
        }
    }

    void setupBaseDirectory(InvocationRequest request) {
        File baseDirectoryFromRequest = null;
        if (request.getBaseDirectory() != null) {
            baseDirectoryFromRequest = request.getBaseDirectory();
        } else {
            File pomFile = request.getPomFile();
            if (pomFile != null) {
                baseDirectoryFromRequest = pomFile.getParentFile();
            }
        }

        if (baseDirectoryFromRequest != null) {
            baseDirectory = baseDirectoryFromRequest;
        }

        if (baseDirectory == null) {
            baseDirectory = new File(System.getProperty("user.dir"));
        } else if (baseDirectory.isFile()) {
            logger.warn(
                    "Specified base directory (" + baseDirectory + ") is a file." + " Using its parent directory...");

            baseDirectory = baseDirectory.getParentFile();
        }

        try {
            baseDirectory = baseDirectory.getCanonicalFile();
        } catch (IOException e) {
            logger.debug("Failed to canonicalize base directory: " + baseDirectory + ". Using as-is.", e);
        }
    }

    /**
     * <p>setLocalRepository.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setLocalRepository(InvocationRequest request, Commandline cli) {
        File localRepositoryDirectory = request.getLocalRepositoryDirectory(this.localRepositoryDirectory);

        if (localRepositoryDirectory != null) {
            try {
                localRepositoryDirectory = localRepositoryDirectory.getCanonicalFile();
            } catch (IOException e) {
                logger.debug(
                        "Failed to canonicalize local repository directory: " + localRepositoryDirectory
                                + ". Using as-is.",
                        e);
            }

            if (!localRepositoryDirectory.isDirectory()) {
                throw new IllegalArgumentException(
                        "Local repository location: '" + localRepositoryDirectory + "' is NOT a directory.");
            }

            cli.createArg().setValue("-D");
            cli.createArg().setValue("maven.repo.local=" + localRepositoryDirectory.getPath());
        }
    }

    /**
     * <p>setReactorBehavior.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setReactorBehavior(InvocationRequest request, Commandline cli) {
        // NOTE: The default is "fail-fast"
        ReactorFailureBehavior failureBehavior = request.getReactorFailureBehavior();

        if (failureBehavior != null) {
            if (ReactorFailureBehavior.FailAtEnd.equals(failureBehavior)) {
                cli.createArg().setValue("-" + ReactorFailureBehavior.FailAtEnd.getShortOption());
            } else if (ReactorFailureBehavior.FailNever.equals(failureBehavior)) {
                cli.createArg().setValue("-" + ReactorFailureBehavior.FailNever.getShortOption());
            }
        }

        if (StringUtils.isNotEmpty(request.getResumeFrom())) {
            cli.createArg().setValue("-rf");
            cli.createArg().setValue(request.getResumeFrom());
        }

        List<String> projectList = request.getProjects();
        if (projectList != null) {
            cli.createArg().setValue("-pl");
            cli.createArg().setValue(StringUtils.join(projectList.iterator(), ","));

            if (request.isAlsoMake()) {
                cli.createArg().setValue("-am");
            }

            if (request.isAlsoMakeDependents()) {
                cli.createArg().setValue("-amd");
            }
        }
    }

    /**
     * <p>setFlags.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setFlags(InvocationRequest request, Commandline cli) {
        if (request.isBatchMode()) {
            cli.createArg().setValue("-B");
        }

        if (request.isOffline()) {
            cli.createArg().setValue("-o");
        }

        if (request.isUpdateSnapshots()) {
            cli.createArg().setValue("-U");
        }

        if (!request.isRecursive()) {
            cli.createArg().setValue("-N");
        }

        if (request.isDebug()) {
            cli.createArg().setValue("-X");
        }
        // this is superseded by -X, if it exists.
        else if (request.isShowErrors()) {
            cli.createArg().setValue("-e");
        }

        CheckSumPolicy checksumPolicy = request.getGlobalChecksumPolicy();
        if (CheckSumPolicy.Fail.equals(checksumPolicy)) {
            cli.createArg().setValue("-C");
        } else if (CheckSumPolicy.Warn.equals(checksumPolicy)) {
            cli.createArg().setValue("-c");
        }

        if (request.isNonPluginUpdates()) {
            cli.createArg().setValue("-npu");
        }

        if (request.isShowVersion()) {
            cli.createArg().setValue("-V");
        }

        if (request.getBuilder() != null) {
            cli.createArg().setValue("-b");
            cli.createArg().setValue(request.getBuilder());
        }

        if (request.isQuiet()) {
            cli.createArg().setValue("-q");
        }

        if (request.isNoTransferProgress()) {
            cli.createArg().setValue("-ntp");
        }
    }

    /**
     * <p>setThreads.</p>
     *
     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
     */
    protected void setThreads(InvocationRequest request, Commandline cli) {
        String threads = request.getThreads();
        if (threads != null && !threads.isEmpty()) {
            cli.createArg().setValue("-T");
            cli.createArg().setValue(threads);
        }
    }

    private void setArgs(InvocationRequest request, Commandline cli) {
        for (String arg : request.getArgs()) {
            cli.createArg().setValue(arg);
        }
    }

    private void setupMavenHome(InvocationRequest request) {
        if (request.getMavenHome() != null) {
            mavenHome = request.getMavenHome();
        } else if (System.getProperty("maven.home") != null) {
            mavenHome = new File(System.getProperty("maven.home"));
        }

        if (mavenHome != null && !mavenHome.isDirectory()) {
            File binDir = mavenHome.getParentFile();
            if (binDir != null && "bin".equals(binDir.getName())) {
                // ah, they specified the mvn
                // executable instead...
                mavenHome = binDir.getParentFile();
            }
        }

        if (mavenHome != null && !mavenHome.isDirectory()) {
            throw new IllegalStateException("Maven home is set to: '" + mavenHome + "' which is not a directory");
        }

        logger.debug("Using maven.home of: '" + mavenHome + "'.");
    }

    /**
     * <p>setupMavenExecutable.</p>
     *
     * @param request a Invoker request
     * @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
     */
    protected void setupMavenExecutable(InvocationRequest request) throws CommandLineConfigurationException {
        if (request.getMavenExecutable() != null) {
            mavenExecutable = request.getMavenExecutable();
        }

        if (mavenExecutable == null || !mavenExecutable.isAbsolute()) {
            String executable;
            if (mavenExecutable != null) {
                executable = mavenExecutable.getPath();
            } else {
                executable = "mvn";
            }

            // firs look in project directory
            mavenExecutable = detectMavenExecutablePerOs(baseDirectory, executable);
            if (mavenExecutable == null) {
                // next maven home
                mavenExecutable = detectMavenExecutablePerOs(mavenHome, "/bin/" + executable);
            }

            if (mavenExecutable != null) {
                try {
                    mavenExecutable = mavenExecutable.getCanonicalFile();
                } catch (IOException e) {
                    logger.debug("Failed to canonicalize maven executable: '" + mavenExecutable + "'. Using as-is.", e);
                }
            } else {
                throw new CommandLineConfigurationException("Maven executable: '" + executable + "'"
                        + " not found at project dir: '" + baseDirectory + "' nor maven home: '" + mavenHome + "'");
            }
        }
    }

    private File detectMavenExecutablePerOs(File baseDirectory, String executable) {
        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            File executableFile = new File(baseDirectory, executable + ".ps1");
            if (executableFile.isFile()) {
                return executableFile;
            }

            executableFile = new File(baseDirectory, executable + ".cmd");
            if (executableFile.isFile()) {
                return executableFile;
            }

            executableFile = new File(baseDirectory, executable + ".bat");
            if (executableFile.isFile()) {
                return executableFile;
            }
        }

        File executableFile = new File(baseDirectory, executable);
        if (executableFile.isFile()) {
            return executableFile;
        }
        return null;
    }

    /**
     * <p>Getter for the field <code>localRepositoryDirectory</code>.</p>
     *
     * @return a {@link java.io.File} object.
     */
    public File getLocalRepositoryDirectory() {
        return localRepositoryDirectory;
    }

    /**
     * <p>Setter for the field <code>localRepositoryDirectory</code>.</p>
     *
     * @param localRepositoryDirectory a {@link java.io.File} object.
     */
    public void setLocalRepositoryDirectory(File localRepositoryDirectory) {
        this.localRepositoryDirectory = localRepositoryDirectory;
    }

    /**
     * <p>Getter for the field <code>logger</code>.</p>
     *
     * @return a {@link org.apache.maven.shared.invoker.InvokerLogger} object.
     */
    public InvokerLogger getLogger() {
        return logger;
    }

    /**
     * <p>Setter for the field <code>logger</code>.</p>
     *
     * @param logger a {@link org.apache.maven.shared.invoker.InvokerLogger} object.
     */
    public void setLogger(InvokerLogger logger) {
        this.logger = logger;
    }

    /**
     * <p>Getter for the field <code>mavenHome</code>.</p>
     *
     * @return a {@link java.io.File} object.
     */
    public File getMavenHome() {
        return mavenHome;
    }

    /**
     * <p>Setter for the field <code>mavenHome</code>.</p>
     *
     * @param mavenHome a {@link java.io.File} object.
     */
    public void setMavenHome(File mavenHome) {
        this.mavenHome = mavenHome;
    }

    /**
     * <p>Getter for the field <code>baseDirectory</code>.</p>
     *
     * @return a {@link java.io.File} object.
     */
    public File getBaseDirectory() {
        return baseDirectory;
    }

    /**
     * <p>Setter for the field <code>baseDirectory</code>.</p>
     *
     * @param baseDirectory a {@link java.io.File} object.
     */
    public void setBaseDirectory(File baseDirectory) {
        this.baseDirectory = baseDirectory;
    }

    /**
     * {@code mavenExecutable} can either be relative to ${maven.home}/bin/ or absolute
     *
     * @param mavenExecutable the executable
     */
    public void setMavenExecutable(File mavenExecutable) {
        this.mavenExecutable = mavenExecutable;
    }

    /**
     * <p>Getter for the field <code>mavenExecutable</code>.</p>
     *
     * @return a {@link java.io.File} object.
     */
    public File getMavenExecutable() {
        return mavenExecutable;
    }
}
