/*
 *  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
 *
 *      https://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.ivy.core.resolve;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.IncludeRule;
import org.apache.ivy.core.module.descriptor.WorkspaceModuleDescriptor;

/**
 * Class collecting usage data for an IvyNode.
 * <p>
 * Usage data contains the configurations required by callers for each root module configuration,
 * the configurations required by caller node and caller configuration, dependency artifacts
 * descriptors declared by callers, include rules declared by callers, and blacklisted data by root
 * module conf.
 * </p>
 */
public class IvyNodeUsage {

    private static final class NodeConf {
        private IvyNode node;

        private String conf;

        public NodeConf(IvyNode node, String conf) {
            if (node == null) {
                throw new NullPointerException("node must not null");
            }
            if (conf == null) {
                throw new NullPointerException("conf must not null");
            }
            this.node = node;
            this.conf = conf;
        }

        public final String getConf() {
            return conf;
        }

        public final IvyNode getNode() {
            return node;
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof NodeConf && getNode().equals(((NodeConf) obj).getNode()) && getConf().equals(((NodeConf) obj).getConf());
        }

        @Override
        public int hashCode() {
            // CheckStyle:MagicNumber| OFF
            int hash = 33;
            hash += getNode().hashCode() * 17;
            hash += getConf().hashCode() * 17;
            // CheckStyle:MagicNumber| OFF
            return hash;
        }

        @Override
        public String toString() {
            return "NodeConf(" + conf + ")";
        }
    }

    private static final class Depender {
        private DependencyDescriptor dd;

        private String dependerConf;

        public Depender(DependencyDescriptor dd, String dependerConf) {
            this.dd = dd;
            this.dependerConf = dependerConf;
        }

        @Override
        public String toString() {
            return dd + " [" + dependerConf + "]";
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Depender)) {
                return false;
            }
            Depender other = (Depender) obj;
            return other.dd == dd && other.dependerConf.equals(dependerConf);
        }

        @Override
        public int hashCode() {
            int hash = 33;
            hash += dd.hashCode() * 13;
            hash += dependerConf.hashCode() * 13;
            return hash;
        }
    }

    private IvyNode node;

    // used to know which configurations of the dependency are required
    // for each root module configuration
    // rootConfName -> confNames
    private Map<String, Set<String>> rootModuleConfs = new HashMap<>();

    private Map<NodeConf, Set<String>> requiredConfs = new HashMap<>();

    private Map<String, Set<Depender>> dependers = new HashMap<>();

    // rootModuleConf -> black list
    private Map<String, IvyNodeBlacklist> blacklisted = new HashMap<>();

    public IvyNodeUsage(IvyNode node) {
        this.node = node;
    }

    protected Collection<String> getRequiredConfigurations(IvyNode in, String inConf) {
        return requiredConfs.get(new NodeConf(in, inConf));
    }

    protected void setRequiredConfs(IvyNode parent, String parentConf, Collection<String> confs) {
        requiredConfs.put(new NodeConf(parent, parentConf), new HashSet<>(confs));
    }

    /**
     * Returns the configurations of the dependency required in a given root module configuration.
     *
     * @param rootModuleConf ditto
     * @return Set&lt;String&gt;
     */
    protected Set<String> getConfigurations(String rootModuleConf) {
        return rootModuleConfs.get(rootModuleConf);
    }

    protected Set<String> addAndGetConfigurations(String rootModuleConf) {
        Set<String> depConfs = rootModuleConfs.get(rootModuleConf);
        if (depConfs == null) {
            depConfs = new HashSet<>();
            rootModuleConfs.put(rootModuleConf, depConfs);
        }
        return depConfs;
    }

    protected Set<String> getRootModuleConfigurations() {
        return rootModuleConfs.keySet();
    }

    public void updateDataFrom(Collection<IvyNodeUsage> usages, String rootModuleConf) {
        for (IvyNodeUsage usage : usages) {
            updateDataFrom(usage, rootModuleConf);
        }
    }

    private void updateDataFrom(IvyNodeUsage usage, String rootModuleConf) {
        // update requiredConfs
        updateMapOfSet(usage.requiredConfs, requiredConfs);

        // update rootModuleConfs
        updateMapOfSetForKey(usage.rootModuleConfs, rootModuleConfs, rootModuleConf);

        // update dependencyArtifacts
        updateMapOfSetForKey(usage.dependers, dependers, rootModuleConf);
    }

    private <K, V> void updateMapOfSet(Map<K, Set<V>> from, Map<K, Set<V>> to) {
        for (K key : from.keySet()) {
            updateMapOfSetForKey(from, to, key);
        }
    }

    private <K, V> void updateMapOfSetForKey(Map<K, Set<V>> from, Map<K, Set<V>> to, K key) {
        Set<V> set = from.get(key);
        if (set != null) {
            Set<V> toupdate = to.get(key);
            if (toupdate != null) {
                toupdate.addAll(set);
            } else {
                to.put(key, new HashSet<>(set));
            }
        }
    }

    private <K, V> void addObjectsForConf(K rootModuleConf, V objectToAdd, Map<K, Set<V>> map) {
        Set<V> set = map.get(rootModuleConf);
        if (set == null) {
            set = new HashSet<>();
            map.put(rootModuleConf, set);
        }
        set.add(objectToAdd);
    }

    public void addUsage(String rootModuleConf, DependencyDescriptor dd, String parentConf) {
        addObjectsForConf(rootModuleConf, new Depender(dd, parentConf), dependers);
    }

    protected Set<DependencyArtifactDescriptor> getDependencyArtifactsSet(String rootModuleConf) {
        if (node.getDescriptor() instanceof WorkspaceModuleDescriptor) {
            // for a module in the "workspace" artifacts will be actually declared by the resolver
            return null;
        }
        Collection<Depender> dependersInConf = dependers.get(rootModuleConf);
        if (dependersInConf == null) {
            return null;
        }
        Set<DependencyArtifactDescriptor> dependencyArtifacts = new HashSet<>();
        for (Depender depender : dependersInConf) {
            DependencyArtifactDescriptor[] dads = depender.dd
                    .getDependencyArtifacts(depender.dependerConf);
            dependencyArtifacts.addAll(Arrays.asList(dads));
        }
        return dependencyArtifacts;
    }

    protected Set<IncludeRule> getDependencyIncludesSet(String rootModuleConf) {
        Collection<Depender> dependersInConf = dependers.get(rootModuleConf);
        if (dependersInConf == null) {
            return null;
        }
        Set<IncludeRule> dependencyIncludes = new HashSet<>();
        for (Depender depender : dependersInConf) {
            IncludeRule[] rules = depender.dd.getIncludeRules(depender.dependerConf);
            if (rules == null || rules.length == 0) {
                // no include rule in at least one depender -> we must include everything,
                // and so return no include rule at all
                return null;
            }
            dependencyIncludes.addAll(Arrays.asList(rules));
        }
        return dependencyIncludes;
    }

    protected void removeRootModuleConf(String rootModuleConf) {
        rootModuleConfs.remove(rootModuleConf);
    }

    protected void blacklist(IvyNodeBlacklist bdata) {
        blacklisted.put(bdata.getRootModuleConf(), bdata);
    }

    /**
     * Indicates if this node has been blacklisted in the given root module conf.
     * <p>
     * A blacklisted node should be considered as if it doesn't even exist on the repository.
     * </p>
     *
     * @param rootModuleConf
     *            the root module conf for which we'd like to know if the node is blacklisted
     *
     * @return true if this node is blacklisted int he given root module conf, false otherwise
     * @see #blacklist(IvyNodeBlacklist)
     */
    protected boolean isBlacklisted(String rootModuleConf) {
        return blacklisted.containsKey(rootModuleConf);
    }

    /**
     * Returns the blacklist data of this node in the given root module conf, or <code>null</code>
     * if this node is not blacklisted in this root module conf.
     *
     * @param rootModuleConf
     *            the root module configuration to consider
     * @return the blacklist data if any
     */
    protected IvyNodeBlacklist getBlacklistData(String rootModuleConf) {
        return blacklisted.get(rootModuleConf);
    }

    protected IvyNode getNode() {
        return node;
    }

    /**
     * Indicates if at least one depender has a transitive dependency descriptor for the given root
     * module conf.
     *
     * @param rootModuleConf
     *            the root module conf to consider
     * @return <code>true</code> if at least one depender has a transitive dependency descriptor for
     *         the given root module conf, <code>false</code> otherwise.
     */
    public boolean hasTransitiveDepender(String rootModuleConf) {
        Set<Depender> dependersSet = dependers.get(rootModuleConf);
        if (dependersSet == null) {
            return false;
        }
        for (Depender depender : dependersSet) {
            if (depender.dd.isTransitive()) {
                return true;
            }
        }
        return false;
    }

}
