/*
 * 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.sling.maven.projectsupport;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.path.PathTranslator;
import org.apache.maven.settings.Settings;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.io.xpp3.BundleListXpp3Reader;
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.DefaultVersionsHelper;
import org.codehaus.mojo.versions.api.UpdateScope;
import org.codehaus.mojo.versions.api.VersionsHelper;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * Displays all bundles that have newer versions available. Highly based upon the
 * display-dependency-updates goal from the Versions plugin.
 *
 * @since 2.0.8
 * @goal display-bundle-updates
 *
 */
public class DisplayBundleUpdatesMojo extends AbstractMojo {

    /**
     * The width to pad info messages.
     */
    private static final int INFO_PAD_SIZE = 72;

    /**
     * @component
     */
    private org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;

    /**
     * The artifact metadata source to use.
     *
     * @component
     * @required
     * @readonly
     */
    private ArtifactMetadataSource artifactMetadataSource;

    /**
     * @parameter expression="${project.remoteArtifactRepositories}"
     * @readonly
     */
    private List<ArtifactRepository> remoteArtifactRepositories;

    /**
     * @parameter expression="${project.pluginArtifactRepositories}"
     * @readonly
     */
    private List<ArtifactRepository> remotePluginRepositories;

    /**
     * @parameter expression="${localRepository}"
     * @readonly
     */
    private ArtifactRepository localRepository;

    /**
     * @component
     */
    private WagonManager wagonManager;

    /**
     * @parameter expression="${settings}"
     * @readonly
     */
    private Settings settings;

    /**
     * settings.xml's server id for the URL. This is used when wagon needs extra
     * authentication information.
     *
     * @parameter expression="${maven.version.rules.serverId}"
     *            default-value="serverId";
     */
    private String serverId;

    /**
     * The Wagon URI of a ruleSet file containing the rules that control how to
     * compare version numbers.
     *
     * @parameter expression="${maven.version.rules}"
     */
    private String rulesUri;

    /**
     * The Maven Session.
     *
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    private MavenSession session;

    /**
     * @component
     */
    private PathTranslator pathTranslator;

    /**
     * @parameter default-value="${basedir}/src/main/bundles/list.xml"
     */
    private File bundleListFile;

    /**
     * Whether to allow snapshots when searching for the latest version of an
     * artifact.
     *
     * @parameter expression="${allowSnapshots}" default-value="false"
     */
    private boolean allowSnapshots;

    /**
     * Our versions helper.
     */
    private VersionsHelper helper;

    @SuppressWarnings("unchecked")
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            BundleList bundleList = readBundleList(bundleListFile);

            Set<Dependency> bundlesAsDependencies = new HashSet<Dependency>();

            for (StartLevel startLevel : bundleList.getStartLevels()) {
                for (Bundle bundle : startLevel.getBundles()) {
                    bundlesAsDependencies.add(asDependency(bundle));
                }
            }

            logUpdates(getHelper().lookupDependenciesUpdates(bundlesAsDependencies, false));
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to read bundle list.", e);
        }

    }

    private Dependency asDependency(Bundle bundle) {
        Dependency dep = new Dependency();
        dep.setGroupId(bundle.getGroupId());
        dep.setArtifactId(bundle.getArtifactId());
        dep.setClassifier(bundle.getClassifier());
        dep.setVersion(bundle.getVersion());
        dep.setType(bundle.getType());

        return dep;
    }

    private VersionsHelper getHelper() throws MojoExecutionException {
        if (helper == null) {
            helper = new DefaultVersionsHelper(artifactFactory, artifactMetadataSource, remoteArtifactRepositories,
                    remotePluginRepositories, localRepository, wagonManager, settings, serverId, rulesUri, getLog(),
                    session, pathTranslator);
        }
        return helper;
    }

    private void logUpdates(Map<Dependency, ArtifactVersions> updates) {
        List<String> withUpdates = new ArrayList<String>();
        List<String> usingCurrent = new ArrayList<String>();
        for (ArtifactVersions versions : updates.values()) {
            String left = "  " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " ";
            final String current = versions.isCurrentVersionDefined() ? versions.getCurrentVersion().toString()
                    : versions.getArtifact().getVersionRange().toString();
            ArtifactVersion latest = versions.getNewestUpdate(UpdateScope.ANY, Boolean.TRUE.equals(allowSnapshots));
            if (latest != null && !versions.isCurrentVersionDefined()) {
                if (versions.getArtifact().getVersionRange().containsVersion(latest)) {
                    latest = null;
                }
            }
            String right = " " + (latest == null ? current : current + " -> " + latest.toString());
            List<String> t = latest == null ? usingCurrent : withUpdates;
            if (right.length() + left.length() + 3 > INFO_PAD_SIZE) {
                t.add(left + "...");
                t.add(StringUtils.leftPad(right, INFO_PAD_SIZE));

            } else {
                t.add(StringUtils.rightPad(left, INFO_PAD_SIZE - right.length(), ".") + right);
            }
        }

        if (usingCurrent.isEmpty() && !withUpdates.isEmpty()) {
            getLog().info("No bundles are using the newest version.");
            getLog().info("");
        } else if (!usingCurrent.isEmpty()) {
            getLog().info("The following bundles are using the newest version:");
            for (String str : usingCurrent) {
                getLog().info(str);
            }
            getLog().info("");
        }
        if (withUpdates.isEmpty() && !usingCurrent.isEmpty()) {
            getLog().info("No bundles have newer versions.");
            getLog().info("");
        } else if (!withUpdates.isEmpty()) {
            getLog().info("The following bundles have newer versions:");
            for (String str : withUpdates) {
                getLog().info(str);
            }
            getLog().info("");
        }
    }

    private BundleList readBundleList(File file) throws IOException, XmlPullParserException {
        BundleListXpp3Reader reader = new BundleListXpp3Reader();
        FileInputStream fis = new FileInputStream(file);
        try {
            return reader.read(fis);
        } finally {
            fis.close();
        }
    }

}
