/*
 * 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.shared.dependency.analyzer;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.Artifact;

/**
 * Project dependencies analysis result.
 *
 * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
 */
public class ProjectDependencyAnalysis {
    // fields -----------------------------------------------------------------

    private final Set<Artifact> usedDeclaredArtifacts;

    private final Map<Artifact, Set<String>> usedUndeclaredArtifacts;

    private final Set<Artifact> unusedDeclaredArtifacts;

    private final Set<Artifact> testArtifactsWithNonTestScope;

    /**
     * <p>Constructor for ProjectDependencyAnalysis.</p>
     */
    public ProjectDependencyAnalysis() {
        this(null, (Map<Artifact, Set<String>>) null, null, null);
    }

    /**
     * <p>Constructor for ProjectDependencyAnalysis to maintain compatibility with old API</p>
     *
     * @param usedDeclaredArtifacts artifacts both used and declared
     * @param usedUndeclaredArtifacts artifacts used but not declared
     * @param unusedDeclaredArtifacts artifacts declared but not used
     */
    public ProjectDependencyAnalysis(
            Set<Artifact> usedDeclaredArtifacts,
            Set<Artifact> usedUndeclaredArtifacts,
            Set<Artifact> unusedDeclaredArtifacts) {
        this(usedDeclaredArtifacts, usedUndeclaredArtifacts, unusedDeclaredArtifacts, Collections.<Artifact>emptySet());
    }

    /**
     * <p>Constructor for ProjectDependencyAnalysis.</p>
     *
     * @param usedDeclaredArtifacts artifacts both used and declared
     * @param usedUndeclaredArtifacts artifacts used but not declared
     * @param unusedDeclaredArtifacts artifacts declared but not used
     * @param testArtifactsWithNonTestScope artifacts only used in tests but not declared with test scope
     */
    public ProjectDependencyAnalysis(
            Set<Artifact> usedDeclaredArtifacts,
            Set<Artifact> usedUndeclaredArtifacts,
            Set<Artifact> unusedDeclaredArtifacts,
            Set<Artifact> testArtifactsWithNonTestScope) {
        this(
                usedDeclaredArtifacts,
                mapWithKeys(usedUndeclaredArtifacts),
                unusedDeclaredArtifacts,
                testArtifactsWithNonTestScope);
    }

    public ProjectDependencyAnalysis(
            Set<Artifact> usedDeclaredArtifacts,
            Map<Artifact, Set<String>> usedUndeclaredArtifacts,
            Set<Artifact> unusedDeclaredArtifacts,
            Set<Artifact> testArtifactsWithNonTestScope) {
        this.usedDeclaredArtifacts = safeCopy(usedDeclaredArtifacts);
        this.usedUndeclaredArtifacts = safeCopy(usedUndeclaredArtifacts);
        this.unusedDeclaredArtifacts = safeCopy(unusedDeclaredArtifacts);
        this.testArtifactsWithNonTestScope = safeCopy(testArtifactsWithNonTestScope);
    }

    /**
     * Returns artifacts both used and declared.
     *
     * @return artifacts both used and declared
     */
    public Set<Artifact> getUsedDeclaredArtifacts() {
        return safeCopy(usedDeclaredArtifacts);
    }

    /**
     * Returns artifacts used but not declared.
     *
     * @return artifacts used but not declared
     */
    public Set<Artifact> getUsedUndeclaredArtifacts() {
        return safeCopy(usedUndeclaredArtifacts.keySet());
    }

    /**
     * Returns artifacts used but not declared.
     *
     * @return artifacts used but not declared
     */
    public Map<Artifact, Set<String>> getUsedUndeclaredArtifactsWithClasses() {
        return safeCopy(usedUndeclaredArtifacts);
    }

    /**
     * Returns artifacts declared but not used.
     *
     * @return artifacts declared but not used
     */
    public Set<Artifact> getUnusedDeclaredArtifacts() {
        return safeCopy(unusedDeclaredArtifacts);
    }

    /**
     * Returns artifacts only used in tests but not declared with test scope.
     *
     * @return  artifacts only used in tests but not declared with test scope
     */
    public Set<Artifact> getTestArtifactsWithNonTestScope() {
        return safeCopy(testArtifactsWithNonTestScope);
    }

    /**
     * Filter non-compile scoped artifacts from unused declared.
     *
     * @return updated project dependency analysis
     * @since 1.3
     */
    public ProjectDependencyAnalysis ignoreNonCompile() {
        Set<Artifact> filteredUnusedDeclared = new HashSet<>(unusedDeclaredArtifacts);
        filteredUnusedDeclared.removeIf(artifact -> !artifact.getScope().equals(Artifact.SCOPE_COMPILE));

        return new ProjectDependencyAnalysis(
                usedDeclaredArtifacts, usedUndeclaredArtifacts, filteredUnusedDeclared, testArtifactsWithNonTestScope);
    }

    /**
     * Force use status of some declared dependencies, to manually fix consequences of bytecode-level analysis which
     * happens to not detect some effective use (constants, annotation with source-retention, javadoc).
     *
     * @param forceUsedDependencies dependencies to move from "unused-declared" to "used-declared", with
     *                              <code>groupId:artifactId</code> format
     * @return updated project dependency analysis
     * @throws ProjectDependencyAnalyzerException if dependencies forced were either not declared or already detected as
     *                                            used
     * @since 1.3
     */
    @SuppressWarnings("UnusedReturnValue")
    public ProjectDependencyAnalysis forceDeclaredDependenciesUsage(String[] forceUsedDependencies)
            throws ProjectDependencyAnalyzerException {
        Set<String> forced = new HashSet<>(Arrays.asList(forceUsedDependencies));

        Set<Artifact> forcedUnusedDeclared = new HashSet<>(unusedDeclaredArtifacts);
        Set<Artifact> forcedUsedDeclared = new HashSet<>(usedDeclaredArtifacts);

        Iterator<Artifact> iter = forcedUnusedDeclared.iterator();
        while (iter.hasNext()) {
            Artifact artifact = iter.next();

            if (forced.remove(artifact.getGroupId() + ':' + artifact.getArtifactId())) {
                // ok, change artifact status from unused-declared to used-declared
                iter.remove();
                forcedUsedDeclared.add(artifact);
            }
        }

        if (!forced.isEmpty()) {
            // trying to force dependencies as used-declared which were not declared or already detected as used
            Set<String> used = new HashSet<>();
            for (Artifact artifact : usedDeclaredArtifacts) {
                String id = artifact.getGroupId() + ':' + artifact.getArtifactId();
                if (forced.remove(id)) {
                    used.add(id);
                }
            }

            StringBuilder builder = new StringBuilder();
            if (!forced.isEmpty()) {
                builder.append("not declared: ").append(forced);
            }
            if (!used.isEmpty()) {
                if (builder.length() > 0) {
                    builder.append(" and ");
                }
                builder.append("declared but already detected as used: ").append(used);
            }
            throw new ProjectDependencyAnalyzerException("Trying to force use of dependencies which are " + builder);
        }

        return new ProjectDependencyAnalysis(
                forcedUsedDeclared, usedUndeclaredArtifacts, forcedUnusedDeclared, testArtifactsWithNonTestScope);
    }

    /**
     * <p>hashCode.</p>
     *
     * @return an int
     */
    public int hashCode() {
        int hashCode = getUsedDeclaredArtifacts().hashCode();
        hashCode = (hashCode * 37) + getUsedUndeclaredArtifacts().hashCode();
        hashCode = (hashCode * 37) + getUnusedDeclaredArtifacts().hashCode();
        hashCode = (hashCode * 37) + getTestArtifactsWithNonTestScope().hashCode();

        return hashCode;
    }

    /** {@inheritDoc} */
    public boolean equals(Object object) {
        if (object instanceof ProjectDependencyAnalysis) {
            ProjectDependencyAnalysis analysis = (ProjectDependencyAnalysis) object;

            return getUsedDeclaredArtifacts().equals(analysis.getUsedDeclaredArtifacts())
                    && getUsedUndeclaredArtifacts().equals(analysis.getUsedUndeclaredArtifacts())
                    && getUnusedDeclaredArtifacts().equals(analysis.getUnusedDeclaredArtifacts())
                    && getTestArtifactsWithNonTestScope().equals(analysis.getTestArtifactsWithNonTestScope());
        }

        return false;
    }

    /**
     * <p>toString.</p>
     *
     * @return a {@link java.lang.String} object.
     */
    public String toString() {
        StringBuilder buffer = new StringBuilder();

        if (!getUsedDeclaredArtifacts().isEmpty()) {
            buffer.append("usedDeclaredArtifacts=").append(getUsedDeclaredArtifacts());
        }

        if (!getUsedUndeclaredArtifacts().isEmpty()) {
            if (buffer.length() > 0) {
                buffer.append(",");
            }

            buffer.append("usedUndeclaredArtifacts=").append(getUsedUndeclaredArtifacts());
        }

        if (!getUnusedDeclaredArtifacts().isEmpty()) {
            if (buffer.length() > 0) {
                buffer.append(",");
            }

            buffer.append("unusedDeclaredArtifacts=").append(getUnusedDeclaredArtifacts());
        }

        if (!getTestArtifactsWithNonTestScope().isEmpty()) {
            if (buffer.length() > 0) {
                buffer.append(",");
            }

            buffer.append("testArtifactsWithNonTestScope=").append(getTestArtifactsWithNonTestScope());
        }

        buffer.insert(0, "[");
        buffer.insert(0, getClass().getName());

        buffer.append("]");

        return buffer.toString();
    }

    // private methods --------------------------------------------------------

    private Set<Artifact> safeCopy(Set<Artifact> set) {
        return (set == null) ? Collections.emptySet() : Collections.unmodifiableSet(new LinkedHashSet<>(set));
    }

    private static Map<Artifact, Set<String>> safeCopy(Map<Artifact, Set<String>> origMap) {
        if (origMap == null) {
            return Collections.emptyMap();
        }

        Map<Artifact, Set<String>> map = new HashMap<>();

        for (Map.Entry<Artifact, Set<String>> e : origMap.entrySet()) {
            map.put(e.getKey(), Collections.unmodifiableSet(new LinkedHashSet<>(e.getValue())));
        }

        return map;
    }

    private static Map<Artifact, Set<String>> mapWithKeys(Set<Artifact> keys) {
        if (keys == null) {
            return Collections.emptyMap();
        }

        Map<Artifact, Set<String>> map = new HashMap<>();

        for (Artifact k : keys) {
            map.put(k, Collections.<String>emptySet());
        }

        return map;
    }
}
