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

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.api.services.Lookup;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.lifecycle.DefaultLifecycles;
import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
import org.apache.maven.lifecycle.Lifecycle;
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
import org.apache.maven.lifecycle.mapping.LifecycleMojo;
import org.apache.maven.lifecycle.mapping.LifecyclePhase;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.InputSource;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Objects.requireNonNull;

/**
 * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
 *
 * @since 3.0
 */
@Singleton
@Named
public class DefaultLifecyclePluginAnalyzer implements LifeCyclePluginAnalyzer {
    public static final String DEFAULTLIFECYCLEBINDINGS_MODELID = "org.apache.maven:maven-core:"
            + DefaultLifecyclePluginAnalyzer.class.getPackage().getImplementationVersion()
            + ":default-lifecycle-bindings";

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final Lookup lookup;

    private final DefaultLifecycles defaultLifeCycles;

    @Inject
    public DefaultLifecyclePluginAnalyzer(Lookup lookup, DefaultLifecycles defaultLifeCycles) {
        this.lookup = requireNonNull(lookup);
        this.defaultLifeCycles = requireNonNull(defaultLifeCycles);
    }

    // These methods deal with construction intact Plugin object that look like they come from a standard
    // <plugin/> block in a Maven POM. We have to do some wiggling to pull the sources of information
    // together and this really shows the problem of constructing a sensible default configuration but
    // it's all encapsulated here so it appears normalized to the POM builder.

    // We are going to take the project packaging and find all plugins in the default lifecycle and create
    // fully populated Plugin objects, including executions with goals and default configuration taken
    // from the plugin.xml inside a plugin.
    //

    @Override
    public Set<Plugin> getPluginsBoundByDefaultToAllLifecycles(String packaging) {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking up lifecycle mappings for packaging " + packaging + " from "
                    + Thread.currentThread().getContextClassLoader());
        }

        LifecycleMapping lifecycleMappingForPackaging = lookupLifecycleMapping(packaging);

        if (lifecycleMappingForPackaging == null) {
            return null;
        }

        Map<Plugin, Plugin> plugins = new LinkedHashMap<>();

        for (Lifecycle lifecycle : defaultLifeCycles.getLifeCycles()) {
            org.apache.maven.lifecycle.mapping.Lifecycle lifecycleConfiguration =
                    lifecycleMappingForPackaging.getLifecycles().get(lifecycle.getId());

            Map<String, LifecyclePhase> phaseToGoalMapping = null;

            if (lifecycleConfiguration != null) {
                phaseToGoalMapping = lifecycleConfiguration.getLifecyclePhases();
            } else if (lifecycle.getDefaultLifecyclePhases() != null) {
                phaseToGoalMapping = lifecycle.getDefaultLifecyclePhases();
            }

            if (phaseToGoalMapping != null) {
                for (Map.Entry<String, LifecyclePhase> goalsForLifecyclePhase : phaseToGoalMapping.entrySet()) {
                    String phase = goalsForLifecyclePhase.getKey();
                    LifecyclePhase goals = goalsForLifecyclePhase.getValue();
                    if (goals != null) {
                        parseLifecyclePhaseDefinitions(plugins, phase, goals);
                    }
                }
            }
        }

        return plugins.keySet();
    }

    /**
     * Performs a lookup using Plexus API to make sure we can look up only "visible" (see Maven classloading) components
     * from current module and for example not extensions coming from other modules.
     */
    private LifecycleMapping lookupLifecycleMapping(final String packaging) {
        return lookup.lookupOptional(LifecycleMapping.class, packaging).orElse(null);
    }

    private void parseLifecyclePhaseDefinitions(Map<Plugin, Plugin> plugins, String phase, LifecyclePhase goals) {
        InputSource inputSource = new InputSource();
        inputSource.setModelId(DEFAULTLIFECYCLEBINDINGS_MODELID);
        InputLocation location = new InputLocation(-1, -1, inputSource);
        location.setLocation(0, location);

        List<LifecycleMojo> mojos = goals.getMojos();
        if (mojos != null) {

            for (int i = 0; i < mojos.size(); i++) {
                LifecycleMojo mojo = mojos.get(i);

                GoalSpec gs = parseGoalSpec(mojo.getGoal());

                if (gs == null) {
                    logger.warn(
                            "Ignored invalid goal specification '{}' from lifecycle mapping for phase {}",
                            mojo.getGoal(),
                            phase);
                    continue;
                }

                Plugin plugin = new Plugin();
                plugin.setGroupId(gs.groupId);
                plugin.setArtifactId(gs.artifactId);
                plugin.setVersion(gs.version);

                plugin.setLocation("", location);
                plugin.setLocation("groupId", location);
                plugin.setLocation("artifactId", location);
                plugin.setLocation("version", location);

                Plugin existing = plugins.get(plugin);
                if (existing != null) {
                    if (existing.getVersion() == null) {
                        existing.setVersion(plugin.getVersion());
                        existing.setLocation("version", location);
                    }
                    plugin = existing;
                } else {
                    plugins.put(plugin, plugin);
                }

                PluginExecution execution = new PluginExecution();
                execution.setId(getExecutionId(plugin, gs.goal));
                execution.setPhase(phase);
                execution.setPriority(i - mojos.size());
                execution.getGoals().add(gs.goal);

                execution.setLocation("", location);
                execution.setLocation("id", location);
                execution.setLocation("phase", location);
                execution.setLocation("goals", location);

                XmlNode lifecycleConfiguration = mojo.getConfiguration();
                if (lifecycleConfiguration != null) {
                    execution.setConfiguration(new Xpp3Dom(lifecycleConfiguration));
                }

                if (mojo.getDependencies() != null) {
                    plugin.setDependencies(mojo.getDependencies());
                }
                plugin.getExecutions().add(execution);
            }
        }
    }

    private GoalSpec parseGoalSpec(String goalSpec) {
        GoalSpec gs = new GoalSpec();

        String[] p = goalSpec.trim().split(":");

        if (p.length == 3) {
            // <groupId>:<artifactId>:<goal>
            gs.groupId = p[0];
            gs.artifactId = p[1];
            gs.goal = p[2];
        } else if (p.length == 4) {
            // <groupId>:<artifactId>:<version>:<goal>
            gs.groupId = p[0];
            gs.artifactId = p[1];
            gs.version = p[2];
            gs.goal = p[3];
        } else {
            // invalid
            gs = null;
        }

        return gs;
    }

    private String getExecutionId(Plugin plugin, String goal) {
        Set<String> existingIds = new HashSet<>();
        for (PluginExecution execution : plugin.getExecutions()) {
            existingIds.add(execution.getId());
        }

        String base = "default-" + goal;
        String id = base;

        for (int index = 1; existingIds.contains(id); index++) {
            id = base + '-' + index;
        }

        return id;
    }

    static class GoalSpec {

        String groupId;

        String artifactId;

        String version;

        String goal;
    }
}
