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

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

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import org.apache.maven.api.model.Dependency;
import org.apache.maven.api.model.DependencyManagement;
import org.apache.maven.api.model.DistributionManagement;
import org.apache.maven.api.model.Model;
import org.apache.maven.api.model.ModelBase;
import org.apache.maven.api.model.Profile;
import org.apache.maven.api.model.Repository;
import org.apache.maven.model.building.DefaultModelBuilder;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.building.ModelBuildingException;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelBuildingResult;
import org.apache.maven.model.building.ModelProblemCollector;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.model.composition.DependencyManagementImporter;
import org.apache.maven.model.inheritance.InheritanceAssembler;
import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.management.DependencyManagementInjector;
import org.apache.maven.model.management.PluginManagementInjector;
import org.apache.maven.model.normalization.ModelNormalizer;
import org.apache.maven.model.path.ModelPathTranslator;
import org.apache.maven.model.path.ModelUrlNormalizer;
import org.apache.maven.model.plugin.LifecycleBindingsInjector;
import org.apache.maven.model.plugin.PluginConfigurationExpander;
import org.apache.maven.model.plugin.ReportConfigurationExpander;
import org.apache.maven.model.profile.DefaultProfileSelector;
import org.apache.maven.model.profile.ProfileActivationContext;
import org.apache.maven.model.profile.ProfileInjector;
import org.apache.maven.model.profile.ProfileSelector;
import org.apache.maven.model.superpom.SuperPomProvider;
import org.apache.maven.model.v4.MavenModelVersion;
import org.apache.maven.model.validation.ModelValidator;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectModelResolver;
import org.apache.maven.repository.internal.ModelCacheFactory;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
class DefaultConsumerPomBuilder implements ConsumerPomBuilder {
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultConsumerPomBuilder.class);

    private static final String BOM_PACKAGING = "bom";

    public static final String POM_PACKAGING = "pom";

    @Inject
    PlexusContainer container;

    @Inject
    ModelCacheFactory modelCacheFactory;

    public Model build(RepositorySystemSession session, MavenProject project, Path src)
            throws ModelBuildingException, ComponentLookupException {
        Model model = project.getModel().getDelegate();
        String packaging = model.getPackaging();
        String originalPackaging = project.getOriginalModel().getPackaging();
        if (POM_PACKAGING.equals(packaging) && !BOM_PACKAGING.equals(originalPackaging)) {
            return buildPom(session, project, src);
        } else {
            return buildNonPom(session, project, src);
        }
    }

    protected Model buildPom(RepositorySystemSession session, MavenProject project, Path src)
            throws ModelBuildingException, ComponentLookupException {
        ModelBuildingResult result = buildModel(session, project, src);
        Model model = result.getRawModel().getDelegate();
        return transform(model, project);
    }

    protected Model buildNonPom(RepositorySystemSession session, MavenProject project, Path src)
            throws ModelBuildingException, ComponentLookupException {
        ModelBuildingResult result = buildModel(session, project, src);
        Model model = result.getEffectiveModel().getDelegate();
        return transform(model, project);
    }

    private ModelBuildingResult buildModel(RepositorySystemSession session, MavenProject project, Path src)
            throws ModelBuildingException, ComponentLookupException {
        ProfileSelector customSelector = new DefaultProfileSelector() {
            @Override
            public List<Profile> getActiveProfilesV4(
                    Collection<Profile> profiles, ProfileActivationContext context, ModelProblemCollector problems) {
                return new ArrayList<>();
            }
        };
        DefaultModelBuilder modelBuilder = new DefaultModelBuilderFactory()
                .setProfileSelector(customSelector)
                // apply currently active ModelProcessor etc. to support extensions like jgitver
                .setProfileInjector(lookup(ProfileInjector.class))
                .setInheritanceAssembler(lookup(InheritanceAssembler.class))
                .setDependencyManagementImporter(lookup(DependencyManagementImporter.class))
                .setDependencyManagementInjector(lookup(DependencyManagementInjector.class))
                .setLifecycleBindingsInjector(lookup(LifecycleBindingsInjector.class))
                .setModelInterpolator(lookup(ModelInterpolator.class))
                .setModelNormalizer(lookup(ModelNormalizer.class))
                .setModelPathTranslator(lookup(ModelPathTranslator.class))
                .setModelProcessor(lookup(ModelProcessor.class))
                .setModelUrlNormalizer(lookup(ModelUrlNormalizer.class))
                .setModelValidator(lookup(ModelValidator.class))
                .setPluginConfigurationExpander(lookup(PluginConfigurationExpander.class))
                .setPluginManagementInjector(lookup(PluginManagementInjector.class))
                .setReportConfigurationExpander(lookup(ReportConfigurationExpander.class))
                .setSuperPomProvider(lookup(SuperPomProvider.class))
                .newInstance();
        DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
        try {
            request.setRootDirectory(project.getRootDirectory());
        } catch (IllegalStateException e) {
            // ignore if we don't have a root directory
        }
        request.setPomFile(src.toFile());
        request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
        request.setLocationTracking(false);
        request.setModelResolver(new ProjectModelResolver(
                session,
                new RequestTrace(null),
                lookup(RepositorySystem.class),
                lookup(RemoteRepositoryManager.class),
                project.getRemoteProjectRepositories(),
                ProjectBuildingRequest.RepositoryMerging.POM_DOMINANT,
                null));
        request.setTransformerContextBuilder(modelBuilder.newTransformerContextBuilder());
        request.setSystemProperties(toProperties(session.getSystemProperties()));
        request.setUserProperties(toProperties(session.getUserProperties()));
        request.setModelCache(modelCacheFactory.createCache(session));
        return modelBuilder.build(request);
    }

    private Properties toProperties(Map<String, String> map) {
        Properties props = new Properties();
        props.putAll(map);
        return props;
    }

    private <T> T lookup(Class<T> clazz) throws ComponentLookupException {
        return container.lookup(clazz);
    }

    static Model transform(Model model, MavenProject project) {
        String packaging = model.getPackaging();
        if (POM_PACKAGING.equals(packaging)) {
            // raw to consumer transform
            model = model.withRoot(false).withModules(null);
            if (model.getParent() != null) {
                model = model.withParent(model.getParent().withRelativePath(null));
            }

            if (!model.isPreserveModelVersion()) {
                model = model.withPreserveModelVersion(false);
                String modelVersion = new MavenModelVersion().getModelVersion(model);
                model = model.withModelVersion(modelVersion);
            }
        } else if (BOM_PACKAGING.equals(packaging)) {
            DependencyManagement dependencyManagement =
                    project.getOriginalModel().getDependencyManagement().getDelegate();
            List<Dependency> dependencies = new ArrayList<>();
            String version = model.getVersion();

            dependencyManagement
                    .getDependencies()
                    .forEach((dependency) -> dependencies.add(dependency.withVersion(version)));
            Model.Builder builder = prune(
                    Model.newBuilder(model, true)
                            .preserveModelVersion(false)
                            .root(false)
                            .parent(null)
                            .dependencyManagement(dependencyManagement.withDependencies(dependencies))
                            .build(null),
                    model);
            builder.packaging(POM_PACKAGING);
            builder.profiles(model.getProfiles().stream()
                    .map(p -> prune(Profile.newBuilder(p, true), p).build())
                    .collect(Collectors.toList()));

            model = builder.build();
            String modelVersion = new MavenModelVersion().getModelVersion(model);
            model = model.withModelVersion(modelVersion);
        } else {
            Model.Builder builder = prune(
                    Model.newBuilder(model, true)
                            .preserveModelVersion(false)
                            .root(false)
                            .parent(null)
                            .build(null),
                    model);
            builder.profiles(model.getProfiles().stream()
                    .map(p -> prune(Profile.newBuilder(p, true), p).build())
                    .collect(Collectors.toList()));
            model = builder.build();
            String modelVersion = new MavenModelVersion().getModelVersion(model);
            model = model.withModelVersion(modelVersion);
        }
        return model;
    }

    private static <T extends ModelBase.Builder> T prune(T builder, ModelBase model) {
        builder.properties(null).reporting(null);
        if (model.getDistributionManagement() != null
                && model.getDistributionManagement().getRelocation() != null) {
            // keep relocation only
            builder.distributionManagement(DistributionManagement.newBuilder()
                    .relocation(model.getDistributionManagement().getRelocation())
                    .build());
        }
        // only keep repositories other than 'central'
        builder.pluginRepositories(pruneRepositories(model.getPluginRepositories()));
        builder.repositories(pruneRepositories(model.getRepositories()));
        return builder;
    }

    private static List<Repository> pruneRepositories(List<Repository> repositories) {
        return repositories.stream()
                .filter(r -> !org.apache.maven.api.Repository.CENTRAL_ID.equals(r.getId()))
                .collect(Collectors.toList());
    }
}
