/*
 * 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.lifecycle;

import javax.inject.Inject;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.MojoExecutionEvent;
import org.apache.maven.execution.MojoExecutionListener;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.execution.ProjectExecutionEvent;
import org.apache.maven.execution.ProjectExecutionListener;
import org.apache.maven.lifecycle.internal.DefaultLifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleTask;
import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
import org.apache.maven.lifecycle.internal.TaskSegment;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.project.MavenProject;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

class LifecycleExecutorTest extends AbstractCoreMavenComponentTestCase {
    @Inject
    private DefaultLifecycleExecutor lifecycleExecutor;

    @Inject
    private DefaultLifecycleTaskSegmentCalculator lifeCycleTaskSegmentCalculator;

    @Inject
    private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;

    @Inject
    private MojoDescriptorCreator mojoDescriptorCreator;

    protected String getProjectsDirectory() {
        return "src/test/projects/lifecycle-executor";
    }

    // -----------------------------------------------------------------------------------------------
    // Tests which exercise the lifecycle executor when it is dealing with default lifecycle phases.
    // -----------------------------------------------------------------------------------------------

    @Test
    void testCalculationOfBuildPlanWithIndividualTaskWherePluginIsSpecifiedInThePom() throws Exception {
        // We are doing something like "mvn resources:resources" where no version is specified but this
        // project we are working on has the version specified in the POM so the version should come from there.
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        assertEquals("project-basic", session.getCurrentProject().getArtifactId());
        assertEquals("1.0", session.getCurrentProject().getVersion());
        List<MojoExecution> executionPlan = getExecutions(calculateExecutionPlan(session, "resources:resources"));
        assertEquals(1, executionPlan.size());
        MojoExecution mojoExecution = executionPlan.get(0);
        assertNotNull(mojoExecution);
        assertEquals(
                "org.apache.maven.plugins",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId());
        assertEquals(
                "maven-resources-plugin",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId());
        assertEquals(
                "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion());
    }

    @Test
    void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanLifecycle() throws Exception {
        // We are doing something like "mvn clean:clean" where no version is specified but this
        // project we are working on has the version specified in the POM so the version should come from there.
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        assertEquals("project-basic", session.getCurrentProject().getArtifactId());
        assertEquals("1.0", session.getCurrentProject().getVersion());
        List<MojoExecution> executionPlan = getExecutions(calculateExecutionPlan(session, "clean"));
        assertEquals(1, executionPlan.size());
        MojoExecution mojoExecution = executionPlan.get(0);
        assertNotNull(mojoExecution);
        assertEquals(
                "org.apache.maven.plugins",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId());
        assertEquals(
                "maven-clean-plugin",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId());
        assertEquals(
                "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion());
    }

    @Test
    void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanCleanGoal() throws Exception {
        // We are doing something like "mvn clean:clean" where no version is specified but this
        // project we are working on has the version specified in the POM so the version should come from there.
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        assertEquals("project-basic", session.getCurrentProject().getArtifactId());
        assertEquals("1.0", session.getCurrentProject().getVersion());
        List<MojoExecution> executionPlan = getExecutions(calculateExecutionPlan(session, "clean:clean"));
        assertEquals(1, executionPlan.size());
        MojoExecution mojoExecution = executionPlan.get(0);
        assertNotNull(mojoExecution);
        assertEquals(
                "org.apache.maven.plugins",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId());
        assertEquals(
                "maven-clean-plugin",
                mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId());
        assertEquals(
                "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion());
    }

    List<MojoExecution> getExecutions(MavenExecutionPlan mavenExecutionPlan) {
        List<MojoExecution> result = new ArrayList<>();
        for (ExecutionPlanItem executionPlanItem : mavenExecutionPlan) {
            result.add(executionPlanItem.getMojoExecution());
        }
        return result;
    }

    // We need to take in multiple lifecycles
    public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifecycle() throws Exception {
        File pom = getProject("project-with-additional-lifecycle-elements");
        MavenSession session = createMavenSession(pom);
        assertEquals(
                "project-with-additional-lifecycle-elements",
                session.getCurrentProject().getArtifactId());
        assertEquals("1.0", session.getCurrentProject().getVersion());
        List<MojoExecution> executionPlan = getExecutions(calculateExecutionPlan(session, "clean", "install"));

        // [01] clean:clean
        // [02] resources:resources
        // [03] compiler:compile
        // [04] it:generate-metadata
        // [05] resources:testResources
        // [06] compiler:testCompile
        // [07] it:generate-test-metadata
        // [08] surefire:test
        // [09] jar:jar
        // [10] install:install
        //
        assertEquals(10, executionPlan.size());

        assertEquals("clean:clean", executionPlan.get(0).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "resources:resources", executionPlan.get(1).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "compiler:compile", executionPlan.get(2).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "it:generate-metadata", executionPlan.get(3).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "resources:testResources",
                executionPlan.get(4).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "compiler:testCompile", executionPlan.get(5).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "it:generate-test-metadata",
                executionPlan.get(6).getMojoDescriptor().getFullGoalName());
        assertEquals("surefire:test", executionPlan.get(7).getMojoDescriptor().getFullGoalName());
        assertEquals("jar:jar", executionPlan.get(8).getMojoDescriptor().getFullGoalName());
        assertEquals("install:install", executionPlan.get(9).getMojoDescriptor().getFullGoalName());
    }

    // We need to take in multiple lifecycles
    public void testCalculationOfBuildPlanWithMultipleExecutionsOfModello() throws Exception {
        File pom = getProject("project-with-multiple-executions");
        MavenSession session = createMavenSession(pom);
        assertEquals(
                "project-with-multiple-executions", session.getCurrentProject().getArtifactId());
        assertEquals("1.0.1", session.getCurrentProject().getVersion());

        MavenExecutionPlan plan = calculateExecutionPlan(session, "clean", "install");

        List<MojoExecution> executions = getExecutions(plan);

        // [01] clean:clean
        // [02] modello:xpp3-writer
        // [03] modello:java
        // [04] modello:xpp3-reader
        // [05] modello:xpp3-writer
        // [06] modello:java
        // [07] modello:xpp3-reader
        // [08] plugin:descriptor
        // [09] resources:resources
        // [10] compiler:compile
        // [11] resources:testResources
        // [12] compiler:testCompile
        // [13] surefire:test
        // [14] jar:jar
        // [15] plugin:addPluginArtifactMetadata
        // [16] install:install
        //

        assertEquals(16, executions.size());

        assertEquals("clean:clean", executions.get(0).getMojoDescriptor().getFullGoalName());
        assertEquals("it:xpp3-writer", executions.get(1).getMojoDescriptor().getFullGoalName());
        assertEquals("it:java", executions.get(2).getMojoDescriptor().getFullGoalName());
        assertEquals("it:xpp3-reader", executions.get(3).getMojoDescriptor().getFullGoalName());
        assertEquals("it:xpp3-writer", executions.get(4).getMojoDescriptor().getFullGoalName());
        assertEquals("it:java", executions.get(5).getMojoDescriptor().getFullGoalName());
        assertEquals("it:xpp3-reader", executions.get(6).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "resources:resources", executions.get(7).getMojoDescriptor().getFullGoalName());
        assertEquals("compiler:compile", executions.get(8).getMojoDescriptor().getFullGoalName());
        assertEquals("plugin:descriptor", executions.get(9).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "resources:testResources",
                executions.get(10).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "compiler:testCompile", executions.get(11).getMojoDescriptor().getFullGoalName());
        assertEquals("surefire:test", executions.get(12).getMojoDescriptor().getFullGoalName());
        assertEquals("jar:jar", executions.get(13).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "plugin:addPluginArtifactMetadata",
                executions.get(14).getMojoDescriptor().getFullGoalName());
        assertEquals("install:install", executions.get(15).getMojoDescriptor().getFullGoalName());

        assertEquals(
                "src/main/mdo/remote-resources.mdo",
                new MojoExecutionXPathContainer(executions.get(1)).getValue("configuration/models[1]/model"));
        assertEquals(
                "src/main/mdo/supplemental-model.mdo",
                new MojoExecutionXPathContainer(executions.get(4)).getValue("configuration/models[1]/model"));
    }

    @Test
    void testLifecycleQueryingUsingADefaultLifecyclePhase() throws Exception {
        File pom = getProject("project-with-additional-lifecycle-elements");
        MavenSession session = createMavenSession(pom);
        assertEquals(
                "project-with-additional-lifecycle-elements",
                session.getCurrentProject().getArtifactId());
        assertEquals("1.0", session.getCurrentProject().getVersion());
        List<MojoExecution> executionPlan = getExecutions(calculateExecutionPlan(session, "package"));

        // [01] resources:resources
        // [02] compiler:compile
        // [03] it:generate-metadata
        // [04] resources:testResources
        // [05] compiler:testCompile
        // [06] plexus-component-metadata:generate-test-metadata
        // [07] surefire:test
        // [08] jar:jar
        //
        assertEquals(8, executionPlan.size());

        assertEquals(
                "resources:resources", executionPlan.get(0).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "compiler:compile", executionPlan.get(1).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "it:generate-metadata", executionPlan.get(2).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "resources:testResources",
                executionPlan.get(3).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "compiler:testCompile", executionPlan.get(4).getMojoDescriptor().getFullGoalName());
        assertEquals(
                "it:generate-test-metadata",
                executionPlan.get(5).getMojoDescriptor().getFullGoalName());
        assertEquals("surefire:test", executionPlan.get(6).getMojoDescriptor().getFullGoalName());
        assertEquals("jar:jar", executionPlan.get(7).getMojoDescriptor().getFullGoalName());
    }

    @Test
    void testLifecyclePluginsRetrievalForDefaultLifecycle() throws Exception {
        List<Plugin> plugins = new ArrayList<>(lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles("jar"));

        assertThat(plugins.toString(), plugins, hasSize(9));
    }

    @Test
    void testPluginConfigurationCreation() throws Exception {
        File pom = getProject("project-with-additional-lifecycle-elements");
        MavenSession session = createMavenSession(pom);
        MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor(
                "org.apache.maven.its.plugins:maven-it-plugin:0.1:java", session, session.getCurrentProject());
        XmlNode dom = MojoDescriptorCreator.convert(mojoDescriptor).getDom();
        System.out.println(dom);
    }

    MavenExecutionPlan calculateExecutionPlan(MavenSession session, String... tasks) throws Exception {
        List<TaskSegment> taskSegments =
                lifeCycleTaskSegmentCalculator.calculateTaskSegments(session, Arrays.asList(tasks));

        TaskSegment mergedSegment = new TaskSegment(false);

        for (TaskSegment taskSegment : taskSegments) {
            mergedSegment.getTasks().addAll(taskSegment.getTasks());
        }

        return lifeCycleExecutionPlanCalculator.calculateExecutionPlan(
                session, session.getCurrentProject(), mergedSegment.getTasks());
    }

    @Test
    void testInvalidGoalName() throws Exception {
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        MojoNotFoundException e = assertThrows(
                MojoNotFoundException.class,
                () -> getExecutions(calculateExecutionPlan(session, "resources:")),
                "expected a MojoNotFoundException");
        assertEquals("", e.getGoal());

        e = assertThrows(
                MojoNotFoundException.class,
                () -> getExecutions(calculateExecutionPlan(
                        session, "org.apache.maven.plugins:maven-resources-plugin:0.1:resources:toomany")),
                "expected a MojoNotFoundException");
        assertEquals("resources:toomany", e.getGoal());
    }

    @Test
    void testPluginPrefixRetrieval() throws Exception {
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        Plugin plugin = mojoDescriptorCreator.findPluginForPrefix("resources", session);
        assertEquals("org.apache.maven.plugins", plugin.getGroupId());
        assertEquals("maven-resources-plugin", plugin.getArtifactId());
    }

    // Prefixes

    @Test
    void testFindingPluginPrefixForCleanClean() throws Exception {
        File pom = getProject("project-basic");
        MavenSession session = createMavenSession(pom);
        Plugin plugin = mojoDescriptorCreator.findPluginForPrefix("clean", session);
        assertNotNull(plugin);
    }

    @Test
    void testSetupMojoExecution() throws Exception {
        File pom = getProject("mojo-configuration");

        MavenSession session = createMavenSession(pom);

        LifecycleTask task = new LifecycleTask("generate-sources");
        MavenExecutionPlan executionPlan = lifeCycleExecutionPlanCalculator.calculateExecutionPlan(
                session, session.getCurrentProject(), Arrays.asList(task), false);

        MojoExecution execution = executionPlan.getMojoExecutions().get(0);
        assertEquals("maven-it-plugin", execution.getArtifactId(), execution.toString());
        assertNull(execution.getConfiguration());

        lifeCycleExecutionPlanCalculator.setupMojoExecution(
                session, session.getCurrentProject(), execution, new HashSet<>());
        assertNotNull(execution.getConfiguration());
        assertEquals("1.0", execution.getConfiguration().getChild("version").getAttribute("default-value"));
    }

    @Test
    void testExecutionListeners() throws Exception {
        final File pom = getProject("project-basic");
        final MavenSession session = createMavenSession(pom);
        session.setProjectDependencyGraph(new ProjectDependencyGraph() {
            @Override
            public List<MavenProject> getUpstreamProjects(MavenProject project, boolean transitive) {
                return Collections.emptyList();
            }

            @Override
            public List<MavenProject> getAllProjects() {
                return session.getAllProjects();
            }

            @Override
            public List<MavenProject> getSortedProjects() {
                return Collections.singletonList(session.getCurrentProject());
            }

            @Override
            public List<MavenProject> getDownstreamProjects(MavenProject project, boolean transitive) {
                return Collections.emptyList();
            }
        });

        final List<String> log = new ArrayList<>();

        MojoExecutionListener mojoListener = new MojoExecutionListener() {
            public void beforeMojoExecution(MojoExecutionEvent event) throws MojoExecutionException {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNotNull(event.getExecution());
                assertNotNull(event.getMojo());
                assertNull(event.getCause());

                log.add("beforeMojoExecution " + event.getProject().getArtifactId() + ":"
                        + event.getExecution().getExecutionId());
            }

            public void afterMojoExecutionSuccess(MojoExecutionEvent event) throws MojoExecutionException {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNotNull(event.getExecution());
                assertNotNull(event.getMojo());
                assertNull(event.getCause());

                log.add("afterMojoExecutionSuccess " + event.getProject().getArtifactId() + ":"
                        + event.getExecution().getExecutionId());
            }

            public void afterExecutionFailure(MojoExecutionEvent event) {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNotNull(event.getExecution());
                assertNotNull(event.getMojo());
                assertNotNull(event.getCause());

                log.add("afterExecutionFailure " + event.getProject().getArtifactId() + ":"
                        + event.getExecution().getExecutionId());
            }
        };
        ProjectExecutionListener projectListener = new ProjectExecutionListener() {
            public void beforeProjectExecution(ProjectExecutionEvent event) throws LifecycleExecutionException {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNull(event.getExecutionPlan());
                assertNull(event.getCause());

                log.add("beforeProjectExecution " + event.getProject().getArtifactId());
            }

            public void beforeProjectLifecycleExecution(ProjectExecutionEvent event)
                    throws LifecycleExecutionException {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNotNull(event.getExecutionPlan());
                assertNull(event.getCause());

                log.add("beforeProjectLifecycleExecution " + event.getProject().getArtifactId());
            }

            public void afterProjectExecutionSuccess(ProjectExecutionEvent event) throws LifecycleExecutionException {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNotNull(event.getExecutionPlan());
                assertNull(event.getCause());

                log.add("afterProjectExecutionSuccess " + event.getProject().getArtifactId());
            }

            public void afterProjectExecutionFailure(ProjectExecutionEvent event) {
                assertNotNull(event.getSession());
                assertNotNull(event.getProject());
                assertNull(event.getExecutionPlan());
                assertNotNull(event.getCause());

                log.add("afterProjectExecutionFailure " + event.getProject().getArtifactId());
            }
        };
        getContainer().lookup(DelegatingProjectExecutionListener.class).addProjectExecutionListener(projectListener);
        getContainer().lookup(DelegatingMojoExecutionListener.class).addMojoExecutionListener(mojoListener);

        try {
            lifecycleExecutor.execute(session);
        } finally {
            getContainer()
                    .lookup(DelegatingProjectExecutionListener.class)
                    .removeProjectExecutionListener(projectListener);
            getContainer().lookup(DelegatingMojoExecutionListener.class).removeMojoExecutionListener(mojoListener);
        }

        List<String> expectedLog = Arrays.asList(
                "beforeProjectExecution project-basic", //
                "beforeProjectLifecycleExecution project-basic", //
                "beforeMojoExecution project-basic:default-resources", //
                "afterMojoExecutionSuccess project-basic:default-resources", //
                "beforeMojoExecution project-basic:default-compile", //
                "afterMojoExecutionSuccess project-basic:default-compile", //
                "beforeMojoExecution project-basic:default-testResources", //
                "afterMojoExecutionSuccess project-basic:default-testResources", //
                "beforeMojoExecution project-basic:default-testCompile", //
                "afterMojoExecutionSuccess project-basic:default-testCompile", //
                "beforeMojoExecution project-basic:default-test", //
                "afterMojoExecutionSuccess project-basic:default-test", //
                "beforeMojoExecution project-basic:default-jar", //
                "afterMojoExecutionSuccess project-basic:default-jar", //
                "afterProjectExecutionSuccess project-basic" //
                );

        assertEventLog(expectedLog, log);
    }

    private static void assertEventLog(List<String> expectedList, List<String> actualList) {
        assertEquals(toString(expectedList), toString(actualList));
    }

    private static String toString(List<String> lines) {
        StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            sb.append(line).append('\n');
        }
        return sb.toString();
    }
}
