/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed 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 com.google.common.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Multiset.Entry;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Spliterator;
import java.util.stream.Collector;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Provides static utility methods for creating and working with {@link Multiset} instances.
 *
 * <p>See the Guava User Guide article on <a href=
 * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multisets"> {@code
 * Multisets}</a>.
 *
 * @author Kevin Bourrillion
 * @author Mike Bostock
 * @author Louis Wasserman
 * @since 2.0
 */
@GwtCompatible
public final class Multisets {
  private Multisets() {}

  /**
   * Returns a {@code Collector} that accumulates elements into a multiset created via the specified
   * {@code Supplier}, whose elements are the result of applying {@code elementFunction} to the
   * inputs, with counts equal to the result of applying {@code countFunction} to the inputs.
   * Elements are added in encounter order.
   *
   * <p>If the mapped elements contain duplicates (according to {@link Object#equals}), the element
   * will be added more than once, with the count summed over all appearances of the element.
   *
   * <p>Note that {@code stream.collect(toMultiset(function, e -> 1, supplier))} is equivalent to
   * {@code stream.map(function).collect(Collectors.toCollection(supplier))}.
   *
   * @since 22.0
   */
  public static <T, E, M extends Multiset<E>> Collector<T, ?, M> toMultiset(
      java.util.function.Function<? super T, E> elementFunction,
      java.util.function.ToIntFunction<? super T> countFunction,
      java.util.function.Supplier<M> multisetSupplier) {
    checkNotNull(elementFunction);
    checkNotNull(countFunction);
    checkNotNull(multisetSupplier);
    return Collector.of(
        multisetSupplier,
        (ms, t) -> ms.add(elementFunction.apply(t), countFunction.applyAsInt(t)),
        (ms1, ms2) -> {
          ms1.addAll(ms2);
          return ms1;
        });
  }

  /**
   * Returns an unmodifiable view of the specified multiset. Query operations on the returned
   * multiset "read through" to the specified multiset, and attempts to modify the returned multiset
   * result in an {@link UnsupportedOperationException}.
   *
   * <p>The returned multiset will be serializable if the specified multiset is serializable.
   *
   * @param multiset the multiset for which an unmodifiable view is to be generated
   * @return an unmodifiable view of the multiset
   */
  public static <E> Multiset<E> unmodifiableMultiset(Multiset<? extends E> multiset) {
    if (multiset instanceof UnmodifiableMultiset || multiset instanceof ImmutableMultiset) {
      @SuppressWarnings("unchecked") // Since it's unmodifiable, the covariant cast is safe
      Multiset<E> result = (Multiset<E>) multiset;
      return result;
    }
    return new UnmodifiableMultiset<E>(checkNotNull(multiset));
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   * @since 10.0
   */
  @Deprecated
  public static <E> Multiset<E> unmodifiableMultiset(ImmutableMultiset<E> multiset) {
    return checkNotNull(multiset);
  }

  static class UnmodifiableMultiset<E> extends ForwardingMultiset<E> implements Serializable {
    final Multiset<? extends E> delegate;

    UnmodifiableMultiset(Multiset<? extends E> delegate) {
      this.delegate = delegate;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Multiset<E> delegate() {
      // This is safe because all non-covariant methods are overridden
      return (Multiset<E>) delegate;
    }

    @MonotonicNonNull transient Set<E> elementSet;

    Set<E> createElementSet() {
      return Collections.<E>unmodifiableSet(delegate.elementSet());
    }

    @Override
    public Set<E> elementSet() {
      Set<E> es = elementSet;
      return (es == null) ? elementSet = createElementSet() : es;
    }

    @MonotonicNonNull transient Set<Multiset.Entry<E>> entrySet;

    @SuppressWarnings("unchecked")
    @Override
    public Set<Multiset.Entry<E>> entrySet() {
      Set<Multiset.Entry<E>> es = entrySet;
      return (es == null)
          // Safe because the returned set is made unmodifiable and Entry
          // itself is readonly
          ? entrySet = (Set) Collections.unmodifiableSet(delegate.entrySet())
          : es;
    }

    @Override
    public Iterator<E> iterator() {
      return Iterators.<E>unmodifiableIterator(delegate.iterator());
    }

    @Override
    public boolean add(E element) {
      throw new UnsupportedOperationException();
    }

    @Override
    public int add(E element, int occurences) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean addAll(Collection<? extends E> elementsToAdd) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean remove(Object element) {
      throw new UnsupportedOperationException();
    }

    @Override
    public int remove(Object element, int occurrences) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeAll(Collection<?> elementsToRemove) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean retainAll(Collection<?> elementsToRetain) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
      throw new UnsupportedOperationException();
    }

    @Override
    public int setCount(E element, int count) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean setCount(E element, int oldCount, int newCount) {
      throw new UnsupportedOperationException();
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns an unmodifiable view of the specified sorted multiset. Query operations on the returned
   * multiset "read through" to the specified multiset, and attempts to modify the returned multiset
   * result in an {@link UnsupportedOperationException}.
   *
   * <p>The returned multiset will be serializable if the specified multiset is serializable.
   *
   * @param sortedMultiset the sorted multiset for which an unmodifiable view is to be generated
   * @return an unmodifiable view of the multiset
   * @since 11.0
   */
  @Beta
  public static <E> SortedMultiset<E> unmodifiableSortedMultiset(SortedMultiset<E> sortedMultiset) {
    // it's in its own file so it can be emulated for GWT
    return new UnmodifiableSortedMultiset<E>(checkNotNull(sortedMultiset));
  }

  /**
   * Returns an immutable multiset entry with the specified element and count. The entry will be
   * serializable if {@code e} is.
   *
   * @param e the element to be associated with the returned entry
   * @param n the count to be associated with the returned entry
   * @throws IllegalArgumentException if {@code n} is negative
   */
  public static <E> Multiset.Entry<E> immutableEntry(@Nullable E e, int n) {
    return new ImmutableEntry<E>(e, n);
  }

  static class ImmutableEntry<E> extends AbstractEntry<E> implements Serializable {
    private final @Nullable E element;
    private final int count;

    ImmutableEntry(@Nullable E element, int count) {
      this.element = element;
      this.count = count;
      checkNonnegative(count, "count");
    }

    @Override
    public final @Nullable E getElement() {
      return element;
    }

    @Override
    public final int getCount() {
      return count;
    }

    public ImmutableEntry<E> nextInBucket() {
      return null;
    }

    private static final long serialVersionUID = 0;
  }

  /**
   * Returns a view of the elements of {@code unfiltered} that satisfy a predicate. The returned
   * multiset is a live view of {@code unfiltered}; changes to one affect the other.
   *
   * <p>The resulting multiset's iterators, and those of its {@code entrySet()} and {@code
   * elementSet()}, do not support {@code remove()}. However, all other multiset methods supported
   * by {@code unfiltered} are supported by the returned multiset. When given an element that
   * doesn't satisfy the predicate, the multiset's {@code add()} and {@code addAll()} methods throw
   * an {@link IllegalArgumentException}. When methods such as {@code removeAll()} and {@code
   * clear()} are called on the filtered multiset, only elements that satisfy the filter will be
   * removed from the underlying multiset.
   *
   * <p>The returned multiset isn't threadsafe or serializable, even if {@code unfiltered} is.
   *
   * <p>Many of the filtered multiset's methods, such as {@code size()}, iterate across every
   * element in the underlying multiset and determine which elements satisfy the filter. When a live
   * view is <i>not</i> needed, it may be faster to copy the returned multiset and use the copy.
   *
   * <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as documented at
   * {@link Predicate#apply}. Do not provide a predicate such as {@code
   * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. (See {@link
   * Iterables#filter(Iterable, Class)} for related functionality.)
   *
   * @since 14.0
   */
  @Beta
  public static <E> Multiset<E> filter(Multiset<E> unfiltered, Predicate<? super E> predicate) {
    if (unfiltered instanceof FilteredMultiset) {
      // Support clear(), removeAll(), and retainAll() when filtering a filtered
      // collection.
      FilteredMultiset<E> filtered = (FilteredMultiset<E>) unfiltered;
      Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
      return new FilteredMultiset<E>(filtered.unfiltered, combinedPredicate);
    }
    return new FilteredMultiset<E>(unfiltered, predicate);
  }

  private static final class FilteredMultiset<E> extends ViewMultiset<E> {
    final Multiset<E> unfiltered;
    final Predicate<? super E> predicate;

    FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate) {
      this.unfiltered = checkNotNull(unfiltered);
      this.predicate = checkNotNull(predicate);
    }

    @Override
    public UnmodifiableIterator<E> iterator() {
      return Iterators.filter(unfiltered.iterator(), predicate);
    }

    @Override
    Set<E> createElementSet() {
      return Sets.filter(unfiltered.elementSet(), predicate);
    }

    @Override
    Iterator<E> elementIterator() {
      throw new AssertionError("should never be called");
    }

    @Override
    Set<Entry<E>> createEntrySet() {
      return Sets.filter(
          unfiltered.entrySet(),
          new Predicate<Entry<E>>() {
            @Override
            public boolean apply(Entry<E> entry) {
              return predicate.apply(entry.getElement());
            }
          });
    }

    @Override
    Iterator<Entry<E>> entryIterator() {
      throw new AssertionError("should never be called");
    }

    @Override
    public int count(@Nullable Object element) {
      int count = unfiltered.count(element);
      if (count > 0) {
        @SuppressWarnings("unchecked") // element is equal to an E
        E e = (E) element;
        return predicate.apply(e) ? count : 0;
      }
      return 0;
    }

    @Override
    public int add(@Nullable E element, int occurrences) {
      checkArgument(
          predicate.apply(element), "Element %s does not match predicate %s", element, predicate);
      return unfiltered.add(element, occurrences);
    }

    @Override
    public int remove(@Nullable Object element, int occurrences) {
      checkNonnegative(occurrences, "occurrences");
      if (occurrences == 0) {
        return count(element);
      } else {
        return contains(element) ? unfiltered.remove(element, occurrences) : 0;
      }
    }
  }

  /**
   * Returns the expected number of distinct elements given the specified elements. The number of
   * distinct elements is only computed if {@code elements} is an instance of {@code Multiset};
   * otherwise the default value of 11 is returned.
   */
  static int inferDistinctElements(Iterable<?> elements) {
    if (elements instanceof Multiset) {
      return ((Multiset<?>) elements).elementSet().size();
    }
    return 11; // initial capacity will be rounded up to 16
  }

  /**
   * Returns an unmodifiable view of the union of two multisets. In the returned multiset, the count
   * of each element is the <i>maximum</i> of its counts in the two backing multisets. The iteration
   * order of the returned multiset matches that of the element set of {@code multiset1} followed by
   * the members of the element set of {@code multiset2} that are not contained in {@code
   * multiset1}, with repeated occurrences of the same element appearing consecutively.
   *
   * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
   * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
   *
   * @since 14.0
   */
  @Beta
  public static <E> Multiset<E> union(
      final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
    checkNotNull(multiset1);
    checkNotNull(multiset2);

    return new ViewMultiset<E>() {
      @Override
      public boolean contains(@Nullable Object element) {
        return multiset1.contains(element) || multiset2.contains(element);
      }

      @Override
      public boolean isEmpty() {
        return multiset1.isEmpty() && multiset2.isEmpty();
      }

      @Override
      public int count(Object element) {
        return Math.max(multiset1.count(element), multiset2.count(element));
      }

      @Override
      Set<E> createElementSet() {
        return Sets.union(multiset1.elementSet(), multiset2.elementSet());
      }

      @Override
      Iterator<E> elementIterator() {
        throw new AssertionError("should never be called");
      }

      @Override
      Iterator<Entry<E>> entryIterator() {
        final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
        final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
        // TODO(lowasser): consider making the entries live views
        return new AbstractIterator<Entry<E>>() {
          @Override
          protected Entry<E> computeNext() {
            if (iterator1.hasNext()) {
              Entry<? extends E> entry1 = iterator1.next();
              E element = entry1.getElement();
              int count = Math.max(entry1.getCount(), multiset2.count(element));
              return immutableEntry(element, count);
            }
            while (iterator2.hasNext()) {
              Entry<? extends E> entry2 = iterator2.next();
              E element = entry2.getElement();
              if (!multiset1.contains(element)) {
                return immutableEntry(element, entry2.getCount());
              }
            }
            return endOfData();
          }
        };
      }
    };
  }

  /**
   * Returns an unmodifiable view of the intersection of two multisets. In the returned multiset,
   * the count of each element is the <i>minimum</i> of its counts in the two backing multisets,
   * with elements that would have a count of 0 not included. The iteration order of the returned
   * multiset matches that of the element set of {@code multiset1}, with repeated occurrences of the
   * same element appearing consecutively.
   *
   * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
   * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
   *
   * @since 2.0
   */
  public static <E> Multiset<E> intersection(
      final Multiset<E> multiset1, final Multiset<?> multiset2) {
    checkNotNull(multiset1);
    checkNotNull(multiset2);

    return new ViewMultiset<E>() {
      @Override
      public int count(Object element) {
        int count1 = multiset1.count(element);
        return (count1 == 0) ? 0 : Math.min(count1, multiset2.count(element));
      }

      @Override
      Set<E> createElementSet() {
        return Sets.intersection(multiset1.elementSet(), multiset2.elementSet());
      }

      @Override
      Iterator<E> elementIterator() {
        throw new AssertionError("should never be called");
      }

      @Override
      Iterator<Entry<E>> entryIterator() {
        final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
        // TODO(lowasser): consider making the entries live views
        return new AbstractIterator<Entry<E>>() {
          @Override
          protected Entry<E> computeNext() {
            while (iterator1.hasNext()) {
              Entry<E> entry1 = iterator1.next();
              E element = entry1.getElement();
              int count = Math.min(entry1.getCount(), multiset2.count(element));
              if (count > 0) {
                return immutableEntry(element, count);
              }
            }
            return endOfData();
          }
        };
      }
    };
  }

  /**
   * Returns an unmodifiable view of the sum of two multisets. In the returned multiset, the count
   * of each element is the <i>sum</i> of its counts in the two backing multisets. The iteration
   * order of the returned multiset matches that of the element set of {@code multiset1} followed by
   * the members of the element set of {@code multiset2} that are not contained in {@code
   * multiset1}, with repeated occurrences of the same element appearing consecutively.
   *
   * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
   * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
   *
   * @since 14.0
   */
  @Beta
  public static <E> Multiset<E> sum(
      final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
    checkNotNull(multiset1);
    checkNotNull(multiset2);

    // TODO(lowasser): consider making the entries live views
    return new ViewMultiset<E>() {
      @Override
      public boolean contains(@Nullable Object element) {
        return multiset1.contains(element) || multiset2.contains(element);
      }

      @Override
      public boolean isEmpty() {
        return multiset1.isEmpty() && multiset2.isEmpty();
      }

      @Override
      public int size() {
        return IntMath.saturatedAdd(multiset1.size(), multiset2.size());
      }

      @Override
      public int count(Object element) {
        return multiset1.count(element) + multiset2.count(element);
      }

      @Override
      Set<E> createElementSet() {
        return Sets.union(multiset1.elementSet(), multiset2.elementSet());
      }

      @Override
      Iterator<E> elementIterator() {
        throw new AssertionError("should never be called");
      }

      @Override
      Iterator<Entry<E>> entryIterator() {
        final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
        final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
        return new AbstractIterator<Entry<E>>() {
          @Override
          protected Entry<E> computeNext() {
            if (iterator1.hasNext()) {
              Entry<? extends E> entry1 = iterator1.next();
              E element = entry1.getElement();
              int count = entry1.getCount() + multiset2.count(element);
              return immutableEntry(element, count);
            }
            while (iterator2.hasNext()) {
              Entry<? extends E> entry2 = iterator2.next();
              E element = entry2.getElement();
              if (!multiset1.contains(element)) {
                return immutableEntry(element, entry2.getCount());
              }
            }
            return endOfData();
          }
        };
      }
    };
  }

  /**
   * Returns an unmodifiable view of the difference of two multisets. In the returned multiset, the
   * count of each element is the result of the <i>zero-truncated subtraction</i> of its count in
   * the second multiset from its count in the first multiset, with elements that would have a count
   * of 0 not included. The iteration order of the returned multiset matches that of the element set
   * of {@code multiset1}, with repeated occurrences of the same element appearing consecutively.
   *
   * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
   * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
   *
   * @since 14.0
   */
  @Beta
  public static <E> Multiset<E> difference(
      final Multiset<E> multiset1, final Multiset<?> multiset2) {
    checkNotNull(multiset1);
    checkNotNull(multiset2);

    // TODO(lowasser): consider making the entries live views
    return new ViewMultiset<E>() {
      @Override
      public int count(@Nullable Object element) {
        int count1 = multiset1.count(element);
        return (count1 == 0) ? 0 : Math.max(0, count1 - multiset2.count(element));
      }

      @Override
      public void clear() {
        throw new UnsupportedOperationException();
      }

      @Override
      Iterator<E> elementIterator() {
        final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
        return new AbstractIterator<E>() {
          @Override
          protected E computeNext() {
            while (iterator1.hasNext()) {
              Entry<E> entry1 = iterator1.next();
              E element = entry1.getElement();
              if (entry1.getCount() > multiset2.count(element)) {
                return element;
              }
            }
            return endOfData();
          }
        };
      }

      @Override
      Iterator<Entry<E>> entryIterator() {
        final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
        return new AbstractIterator<Entry<E>>() {
          @Override
          protected Entry<E> computeNext() {
            while (iterator1.hasNext()) {
              Entry<E> entry1 = iterator1.next();
              E element = entry1.getElement();
              int count = entry1.getCount() - multiset2.count(element);
              if (count > 0) {
                return immutableEntry(element, count);
              }
            }
            return endOfData();
          }
        };
      }

      @Override
      int distinctElements() {
        return Iterators.size(entryIterator());
      }
    };
  }

  /**
   * Returns {@code true} if {@code subMultiset.count(o) <= superMultiset.count(o)} for all {@code
   * o}.
   *
   * @since 10.0
   */
  @CanIgnoreReturnValue
  public static boolean containsOccurrences(Multiset<?> superMultiset, Multiset<?> subMultiset) {
    checkNotNull(superMultiset);
    checkNotNull(subMultiset);
    for (Entry<?> entry : subMultiset.entrySet()) {
      int superCount = superMultiset.count(entry.getElement());
      if (superCount < entry.getCount()) {
        return false;
      }
    }
    return true;
  }

  /**
   * Modifies {@code multisetToModify} so that its count for an element {@code e} is at most {@code
   * multisetToRetain.count(e)}.
   *
   * <p>To be precise, {@code multisetToModify.count(e)} is set to {@code
   * Math.min(multisetToModify.count(e), multisetToRetain.count(e))}. This is similar to {@link
   * #intersection(Multiset, Multiset) intersection} {@code (multisetToModify, multisetToRetain)},
   * but mutates {@code multisetToModify} instead of returning a view.
   *
   * <p>In contrast, {@code multisetToModify.retainAll(multisetToRetain)} keeps all occurrences of
   * elements that appear at all in {@code multisetToRetain}, and deletes all occurrences of all
   * other elements.
   *
   * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
   * @since 10.0
   */
  @CanIgnoreReturnValue
  public static boolean retainOccurrences(
      Multiset<?> multisetToModify, Multiset<?> multisetToRetain) {
    return retainOccurrencesImpl(multisetToModify, multisetToRetain);
  }

  /** Delegate implementation which cares about the element type. */
  private static <E> boolean retainOccurrencesImpl(
      Multiset<E> multisetToModify, Multiset<?> occurrencesToRetain) {
    checkNotNull(multisetToModify);
    checkNotNull(occurrencesToRetain);
    // Avoiding ConcurrentModificationExceptions is tricky.
    Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
    boolean changed = false;
    while (entryIterator.hasNext()) {
      Entry<E> entry = entryIterator.next();
      int retainCount = occurrencesToRetain.count(entry.getElement());
      if (retainCount == 0) {
        entryIterator.remove();
        changed = true;
      } else if (retainCount < entry.getCount()) {
        multisetToModify.setCount(entry.getElement(), retainCount);
        changed = true;
      }
    }
    return changed;
  }

  /**
   * For each occurrence of an element {@code e} in {@code occurrencesToRemove}, removes one
   * occurrence of {@code e} in {@code multisetToModify}.
   *
   * <p>Equivalently, this method modifies {@code multisetToModify} so that {@code
   * multisetToModify.count(e)} is set to {@code Math.max(0, multisetToModify.count(e) -
   * Iterables.frequency(occurrencesToRemove, e))}.
   *
   * <p>This is <i>not</i> the same as {@code multisetToModify.} {@link Multiset#removeAll
   * removeAll}{@code (occurrencesToRemove)}, which removes all occurrences of elements that appear
   * in {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent to, albeit
   * sometimes more efficient than, the following:
   *
   * <pre>{@code
   * for (E e : occurrencesToRemove) {
   *   multisetToModify.remove(e);
   * }
   * }</pre>
   *
   * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
   * @since 18.0 (present in 10.0 with a requirement that the second parameter be a {@code
   *     Multiset})
   */
  @CanIgnoreReturnValue
  public static boolean removeOccurrences(
      Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
    if (occurrencesToRemove instanceof Multiset) {
      return removeOccurrences(multisetToModify, (Multiset<?>) occurrencesToRemove);
    } else {
      checkNotNull(multisetToModify);
      checkNotNull(occurrencesToRemove);
      boolean changed = false;
      for (Object o : occurrencesToRemove) {
        changed |= multisetToModify.remove(o);
      }
      return changed;
    }
  }

  /**
   * For each occurrence of an element {@code e} in {@code occurrencesToRemove}, removes one
   * occurrence of {@code e} in {@code multisetToModify}.
   *
   * <p>Equivalently, this method modifies {@code multisetToModify} so that {@code
   * multisetToModify.count(e)} is set to {@code Math.max(0, multisetToModify.count(e) -
   * occurrencesToRemove.count(e))}.
   *
   * <p>This is <i>not</i> the same as {@code multisetToModify.} {@link Multiset#removeAll
   * removeAll}{@code (occurrencesToRemove)}, which removes all occurrences of elements that appear
   * in {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent to, albeit
   * sometimes more efficient than, the following:
   *
   * <pre>{@code
   * for (E e : occurrencesToRemove) {
   *   multisetToModify.remove(e);
   * }
   * }</pre>
   *
   * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
   * @since 10.0 (missing in 18.0 when only the overload taking an {@code Iterable} was present)
   */
  @CanIgnoreReturnValue
  public static boolean removeOccurrences(
      Multiset<?> multisetToModify, Multiset<?> occurrencesToRemove) {
    checkNotNull(multisetToModify);
    checkNotNull(occurrencesToRemove);

    boolean changed = false;
    Iterator<? extends Entry<?>> entryIterator = multisetToModify.entrySet().iterator();
    while (entryIterator.hasNext()) {
      Entry<?> entry = entryIterator.next();
      int removeCount = occurrencesToRemove.count(entry.getElement());
      if (removeCount >= entry.getCount()) {
        entryIterator.remove();
        changed = true;
      } else if (removeCount > 0) {
        multisetToModify.remove(entry.getElement(), removeCount);
        changed = true;
      }
    }
    return changed;
  }

  /**
   * Implementation of the {@code equals}, {@code hashCode}, and {@code toString} methods of {@link
   * Multiset.Entry}.
   */
  abstract static class AbstractEntry<E> implements Multiset.Entry<E> {
    /**
     * Indicates whether an object equals this entry, following the behavior specified in {@link
     * Multiset.Entry#equals}.
     */
    @Override
    public boolean equals(@Nullable Object object) {
      if (object instanceof Multiset.Entry) {
        Multiset.Entry<?> that = (Multiset.Entry<?>) object;
        return this.getCount() == that.getCount()
            && Objects.equal(this.getElement(), that.getElement());
      }
      return false;
    }

    /**
     * Return this entry's hash code, following the behavior specified in {@link
     * Multiset.Entry#hashCode}.
     */
    @Override
    public int hashCode() {
      E e = getElement();
      return ((e == null) ? 0 : e.hashCode()) ^ getCount();
    }

    /**
     * Returns a string representation of this multiset entry. The string representation consists of
     * the associated element if the associated count is one, and otherwise the associated element
     * followed by the characters " x " (space, x and space) followed by the count. Elements and
     * counts are converted to strings as by {@code String.valueOf}.
     */
    @Override
    public String toString() {
      String text = String.valueOf(getElement());
      int n = getCount();
      return (n == 1) ? text : (text + " x " + n);
    }
  }

  /** An implementation of {@link Multiset#equals}. */
  static boolean equalsImpl(Multiset<?> multiset, @Nullable Object object) {
    if (object == multiset) {
      return true;
    }
    if (object instanceof Multiset) {
      Multiset<?> that = (Multiset<?>) object;
      /*
       * We can't simply check whether the entry sets are equal, since that
       * approach fails when a TreeMultiset has a comparator that returns 0
       * when passed unequal elements.
       */

      if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) {
        return false;
      }
      for (Entry<?> entry : that.entrySet()) {
        if (multiset.count(entry.getElement()) != entry.getCount()) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  /** An implementation of {@link Multiset#addAll}. */
  static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) {
    checkNotNull(self);
    checkNotNull(elements);
    if (elements instanceof Multiset) {
      return addAllImpl(self, cast(elements));
    } else if (elements.isEmpty()) {
      return false;
    } else {
      return Iterators.addAll(self, elements.iterator());
    }
  }

  /** A specialization of {@code addAllImpl} for when {@code elements} is itself a Multiset. */
  private static <E> boolean addAllImpl(Multiset<E> self, Multiset<? extends E> elements) {
    if (elements.isEmpty()) {
      return false;
    }
    elements.forEachEntry(self::add);
    return true;
  }

  /** An implementation of {@link Multiset#removeAll}. */
  static boolean removeAllImpl(Multiset<?> self, Collection<?> elementsToRemove) {
    Collection<?> collection =
        (elementsToRemove instanceof Multiset)
            ? ((Multiset<?>) elementsToRemove).elementSet()
            : elementsToRemove;

    return self.elementSet().removeAll(collection);
  }

  /** An implementation of {@link Multiset#retainAll}. */
  static boolean retainAllImpl(Multiset<?> self, Collection<?> elementsToRetain) {
    checkNotNull(elementsToRetain);
    Collection<?> collection =
        (elementsToRetain instanceof Multiset)
            ? ((Multiset<?>) elementsToRetain).elementSet()
            : elementsToRetain;

    return self.elementSet().retainAll(collection);
  }

  /** An implementation of {@link Multiset#setCount(Object, int)}. */
  static <E> int setCountImpl(Multiset<E> self, E element, int count) {
    checkNonnegative(count, "count");

    int oldCount = self.count(element);

    int delta = count - oldCount;
    if (delta > 0) {
      self.add(element, delta);
    } else if (delta < 0) {
      self.remove(element, -delta);
    }

    return oldCount;
  }

  /** An implementation of {@link Multiset#setCount(Object, int, int)}. */
  static <E> boolean setCountImpl(Multiset<E> self, E element, int oldCount, int newCount) {
    checkNonnegative(oldCount, "oldCount");
    checkNonnegative(newCount, "newCount");

    if (self.count(element) == oldCount) {
      self.setCount(element, newCount);
      return true;
    } else {
      return false;
    }
  }

  static <E> Iterator<E> elementIterator(Iterator<Entry<E>> entryIterator) {
    return new TransformedIterator<Entry<E>, E>(entryIterator) {
      @Override
      E transform(Entry<E> entry) {
        return entry.getElement();
      }
    };
  }

  abstract static class ElementSet<E> extends Sets.ImprovedAbstractSet<E> {
    abstract Multiset<E> multiset();

    @Override
    public void clear() {
      multiset().clear();
    }

    @Override
    public boolean contains(Object o) {
      return multiset().contains(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
      return multiset().containsAll(c);
    }

    @Override
    public boolean isEmpty() {
      return multiset().isEmpty();
    }

    @Override
    public abstract Iterator<E> iterator();

    @Override
    public boolean remove(Object o) {
      return multiset().remove(o, Integer.MAX_VALUE) > 0;
    }

    @Override
    public int size() {
      return multiset().entrySet().size();
    }
  }

  abstract static class EntrySet<E> extends Sets.ImprovedAbstractSet<Entry<E>> {
    abstract Multiset<E> multiset();

    @Override
    public boolean contains(@Nullable Object o) {
      if (o instanceof Entry) {
        /*
         * The GWT compiler wrongly issues a warning here.
         */
        @SuppressWarnings("cast")
        Entry<?> entry = (Entry<?>) o;
        if (entry.getCount() <= 0) {
          return false;
        }
        int count = multiset().count(entry.getElement());
        return count == entry.getCount();
      }
      return false;
    }

    // GWT compiler warning; see contains().
    @SuppressWarnings("cast")
    @Override
    public boolean remove(Object object) {
      if (object instanceof Multiset.Entry) {
        Entry<?> entry = (Entry<?>) object;
        Object element = entry.getElement();
        int entryCount = entry.getCount();
        if (entryCount != 0) {
          // Safe as long as we never add a new entry, which we won't.
          @SuppressWarnings("unchecked")
          Multiset<Object> multiset = (Multiset) multiset();
          return multiset.setCount(element, entryCount, 0);
        }
      }
      return false;
    }

    @Override
    public void clear() {
      multiset().clear();
    }
  }

  /** An implementation of {@link Multiset#iterator}. */
  static <E> Iterator<E> iteratorImpl(Multiset<E> multiset) {
    return new MultisetIteratorImpl<E>(multiset, multiset.entrySet().iterator());
  }

  static final class MultisetIteratorImpl<E> implements Iterator<E> {
    private final Multiset<E> multiset;
    private final Iterator<Entry<E>> entryIterator;
    @MonotonicNonNull private Entry<E> currentEntry;

    /** Count of subsequent elements equal to current element */
    private int laterCount;

    /** Count of all elements equal to current element */
    private int totalCount;

    private boolean canRemove;

    MultisetIteratorImpl(Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
      this.multiset = multiset;
      this.entryIterator = entryIterator;
    }

    @Override
    public boolean hasNext() {
      return laterCount > 0 || entryIterator.hasNext();
    }

    @Override
    public E next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      if (laterCount == 0) {
        currentEntry = entryIterator.next();
        totalCount = laterCount = currentEntry.getCount();
      }
      laterCount--;
      canRemove = true;
      return currentEntry.getElement();
    }

    @Override
    public void remove() {
      checkRemove(canRemove);
      if (totalCount == 1) {
        entryIterator.remove();
      } else {
        multiset.remove(currentEntry.getElement());
      }
      totalCount--;
      canRemove = false;
    }
  }

  static <E> Spliterator<E> spliteratorImpl(Multiset<E> multiset) {
    Spliterator<Entry<E>> entrySpliterator = multiset.entrySet().spliterator();
    return CollectSpliterators.flatMap(
        entrySpliterator,
        entry -> Collections.nCopies(entry.getCount(), entry.getElement()).spliterator(),
        Spliterator.SIZED
            | (entrySpliterator.characteristics()
                & (Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE)),
        multiset.size());
  }

  /** An implementation of {@link Multiset#size}. */
  static int linearTimeSizeImpl(Multiset<?> multiset) {
    long size = 0;
    for (Entry<?> entry : multiset.entrySet()) {
      size += entry.getCount();
    }
    return Ints.saturatedCast(size);
  }

  /** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */
  static <T> Multiset<T> cast(Iterable<T> iterable) {
    return (Multiset<T>) iterable;
  }

  /**
   * Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order is
   * highest count first, with ties broken by the iteration order of the original multiset.
   *
   * @since 11.0
   */
  @Beta
  public static <E> ImmutableMultiset<E> copyHighestCountFirst(Multiset<E> multiset) {
    Entry<E>[] entries = (Entry<E>[]) multiset.entrySet().toArray(new Entry[0]);
    Arrays.sort(entries, DecreasingCount.INSTANCE);
    return ImmutableMultiset.copyFromEntries(Arrays.asList(entries));
  }

  private static final class DecreasingCount implements Comparator<Entry<?>> {
    static final DecreasingCount INSTANCE = new DecreasingCount();

    @Override
    public int compare(Entry<?> entry1, Entry<?> entry2) {
      return entry2.getCount() - entry1.getCount(); // subtracting two nonnegative integers
    }
  }

  /**
   * An {@link AbstractMultiset} with additional default implementations, some of them linear-time
   * implementations in terms of {@code elementSet} and {@code entrySet}.
   */
  private abstract static class ViewMultiset<E> extends AbstractMultiset<E> {
    @Override
    public int size() {
      return linearTimeSizeImpl(this);
    }

    @Override
    public void clear() {
      elementSet().clear();
    }

    @Override
    public Iterator<E> iterator() {
      return iteratorImpl(this);
    }

    @Override
    int distinctElements() {
      return elementSet().size();
    }
  }
}
