/*
 * 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.openejb.maven.jarstxt;

import edu.emory.mathcs.backport.java.util.Collections;
import org.apache.commons.lang3.text.StrLookup;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.ProvisioningUtil;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

@Mojo(name = "generate", threadSafe = true,
        requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.COMPILE)
public class JarsTxtMojo extends AbstractMojo {
    public static final String JAR = "jar";
    @Component
    protected MavenProject project;

    @Parameter(property = "outputFile", defaultValue = "${project.build.directory}/${project.build.finalName}/WEB-INF/jars.txt" )
    protected File outputFile;

    @Parameter(property = "hash")
    protected String hashAlgo;

    @Parameter(property = "useTimeStamp", defaultValue = "false")
    protected boolean useTimeStamp;

    @Component
    protected ArtifactFactory factory;

    @Component
    protected ArtifactResolver resolver;

    @Parameter(defaultValue = "${localRepository}", readonly = true)
    protected ArtifactRepository local;

    @Parameter(defaultValue = "${project.remoteArtifactRepositories}", readonly = true)
    protected List<ArtifactRepository> remoteRepos;

    @Parameter
    protected List<String> additionals;

    @Parameter
    protected Map<String, String> placeHolders;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (!outputFile.getParentFile().exists()) {
            FileUtils.mkdir(outputFile.getParentFile().getAbsolutePath());
        }

        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(outputFile));

            final TreeSet<String> set = new TreeSet<>();

            for (final Artifact a : (Set<Artifact>) project.getArtifacts()) {
                if (!acceptScope(a.getScope()) || !acceptType(a.getType())) {
                    continue;
                }

                a.setScope(Artifact.SCOPE_PROVIDED);

                final StringBuilder line = new StringBuilder("mvn:")
                        .append(a.getGroupId()).append("/")
                        .append(a.getArtifactId()).append("/")
                        .append(version(a));

                final boolean isJar = JAR.equals(a.getType());
                if (!isJar) {
                    line.append("/").append(a.getType());
                }

                if (a.getClassifier() != null) {
                    if (isJar) {
                        line.append("/").append(JAR);
                    }
                    line.append("/").append(a.getClassifier());
                }

                if (hashAlgo != null) {
                    final Artifact artifact = factory.createDependencyArtifact(a.getGroupId(), a.getArtifactId(), VersionRange.createFromVersion(a.getVersion()), a.getType(), a.getClassifier(), a.getScope());
                    try {
                        resolver.resolve(artifact, remoteRepos, local);
                    } catch (final ArtifactResolutionException | ArtifactNotFoundException e) {
                        throw new MojoExecutionException(e.getMessage(), e);
                    }
                    final File file = artifact.getFile();
                    line.append("|").append(Files.hash((Set<URL>) Collections.singleton(file.toURI().toURL()), hashAlgo))
                        .append("|").append(hashAlgo);
                }

                set.add(line.toString());
            }

            if (additionals != null) {
                if (placeHolders == null) {
                    placeHolders = new HashMap<>();
                }

                final StrSubstitutor lookup = new StrSubstitutor(StrLookup.mapLookup(placeHolders));

                for (final String line : additionals) {
                    final StringBuilder builder = new StringBuilder(line);
                    if (hashAlgo != null) {
                        builder.append("|").append(Files.hash(urls(line, lookup), hashAlgo))
                                .append("|").append(hashAlgo);
                    }
                    set.add(builder.toString());
                }
            }

            // written after to be sorted, more readable
            for (final String line : set) {
                writer.write(line);
                writer.write("\n");
            }

            writer.flush();
        } catch (final IOException e) {
            getLog().error(e.getMessage(), e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (final IOException e) {
                    // no-op
                }
            }
        }
    }

    private Set<URL> urls(final String line, final StrSubstitutor lookup) {
        final Set<URL> urls = new HashSet<>();
        for (final String location : ProvisioningUtil.realLocation(lookup.replace(line))) { // should have 1 item
            try {
                urls.add(new File(location).toURI().toURL());
            } catch (final MalformedURLException e) {
                throw new IllegalArgumentException(e);
            }
        }
        return urls;
    }

    private String version(final Artifact a) {
        if (!useTimeStamp && a.getBaseVersion().endsWith("SNAPSHOT")) {
            return a.getBaseVersion();
        }
        return a.getVersion();
    }

    private boolean acceptType(final String type) {
        return "jar".equals(type) || "zip".equals(type);
    }

    private boolean acceptScope(final String scope) {
        return Artifact.SCOPE_COMPILE.equals(scope) || Artifact.SCOPE_RUNTIME.equals(scope);
    }
}
