/*
 * 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.sshd.common.util;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.apache.sshd.common.util.functors.UnaryEquator;

/**
 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
 */
public final class GenericUtils {

    public static final byte[] EMPTY_BYTE_ARRAY = {};
    public static final char[] EMPTY_CHAR_ARRAY = {};
    public static final String[] EMPTY_STRING_ARRAY = {};
    public static final Object[] EMPTY_OBJECT_ARRAY = {};
    public static final boolean[] EMPTY_BOOLEAN_ARRAY = {};

    /**
     * A value indicating a {@code null} value - to be used as a placeholder where {@code null}s are not allowed
     */
    public static final Object NULL = new Object();

    /**
     * The complement of {@link String#CASE_INSENSITIVE_ORDER}
     */
    public static final Comparator<String> CASE_SENSITIVE_ORDER = (s1, s2) -> {
        if (s1 == s2) {
            return 0;
        } else {
            return s1.compareTo(s2);
        }
    };

    public static final String QUOTES = "\"'";

    private GenericUtils() {
        throw new UnsupportedOperationException("No instance");
    }

    public static String trimToEmpty(String s) {
        if (s == null) {
            return "";
        } else {
            return s.trim();
        }
    }

    public static String replaceWhitespaceAndTrim(String s) {
        if (s != null) {
            s = s.replace('\t', ' ');
        }

        return trimToEmpty(s);
    }

    /**
     * <p>
     * Replace a String with another String inside a larger String, for the first <code>max</code> values of the search
     * String.
     * </p>
     *
     * <p>
     * A {@code null} reference passed to this method is a no-op.
     * </p>
     *
     * @param  text text to search and replace in
     * @param  repl String to search for
     * @param  with String to replace with
     * @param  max  maximum number of values to replace, or <code>-1</code> if no maximum
     * @return      the text with any replacements processed
     * @author      Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
     * @author      Magesh Umasankar
     * @author      <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
     * @author      <a href="mailto:levylambert@tiscali-dsl.de">Antoine Levy-Lambert</a>
     */
    @SuppressWarnings("PMD.AssignmentInOperand")
    public static String replace(String text, String repl, String with, int max) {
        if ((text == null) || (repl == null) || (with == null) || (repl.length() == 0)) {
            return text;
        }

        int start = 0;
        StringBuilder buf = new StringBuilder(text.length());
        for (int end = text.indexOf(repl, start); end != -1; end = text.indexOf(repl, start)) {
            buf.append(text.substring(start, end)).append(with);
            start = end + repl.length();

            if (--max == 0) {
                break;
            }
        }
        buf.append(text.substring(start));
        return buf.toString();
    }

    /**
     * @param  s The {@link String} value to calculate the hash code on - may be {@code null}/empty in which case a
     *           value of zero is returned
     * @return   The calculated hash code
     * @see      #hashCode(String, Boolean)
     */
    public static int hashCode(String s) {
        return hashCode(s, null);
    }

    /**
     * @param  s            The {@link String} value to calculate the hash code on - may be {@code null}/empty in which
     *                      case a value of zero is returned
     * @param  useUppercase Whether to convert the string to uppercase, lowercase or not at all:
     *                      <UL>
     *                      <LI>{@code null} - no conversion</LI>
     *                      <LI>{@link Boolean#TRUE} - get hash code of uppercase</LI>
     *                      <LI>{@link Boolean#FALSE} - get hash code of lowercase</LI>
     *                      </UL>
     * @return              The calculated hash code
     */
    public static int hashCode(String s, Boolean useUppercase) {
        if (isEmpty(s)) {
            return 0;
        } else if (useUppercase == null) {
            return s.hashCode();
        } else if (useUppercase.booleanValue()) {
            return s.toUpperCase().hashCode();
        } else {
            return s.toLowerCase().hashCode();
        }
    }

    public static int safeCompare(String s1, String s2, boolean caseSensitive) {
        if (UnaryEquator.isSameReference(s1, s2)) {
            return 0;
        } else if (s1 == null) {
            return +1; // push null(s) to end
        } else if (s2 == null) {
            return -1; // push null(s) to end
        } else if (caseSensitive) {
            return s1.compareTo(s2);
        } else {
            return s1.compareToIgnoreCase(s2);
        }
    }

    public static int length(CharSequence cs) {
        return cs == null ? 0 : cs.length();
    }

    public static boolean isEmpty(CharSequence cs) {
        return length(cs) <= 0;
    }

    public static boolean isNotEmpty(CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * <p>
     * Checks if a CharSequence is empty (""), null or whitespace only.
     * </p>
     *
     * <p>
     * Whitespace is defined by {@link Character#isWhitespace(char)}.
     * </p>
     *
     * <pre>
     * GenericUtils.isBlank(null)      = true
     * GenericUtils.isBlank("")        = true
     * GenericUtils.isBlank(" ")       = true
     * GenericUtils.isBlank("bob")     = false
     * GenericUtils.isBlank("  bob  ") = false
     * </pre>
     *
     * @param  cs the CharSequence to check, may be null
     * @return    {@code true} if the CharSequence is null, empty or whitespace only
     */
    public static boolean isBlank(final CharSequence cs) {
        int strLen = cs != null ? cs.length() : 0;
        if (cs == null || strLen == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNotBlank(final CharSequence cs) {
        return !isBlank(cs);
    }

    public static List<String> filterToNotBlank(final List<String> values) {
        return values.stream().filter(GenericUtils::isNotBlank).collect(Collectors.toList());
    }

    public static int indexOf(CharSequence cs, char c) {
        int len = length(cs);
        for (int pos = 0; pos < len; pos++) {
            char ch = cs.charAt(pos);
            if (ch == c) {
                return pos;
            }
        }

        return -1;
    }

    public static int lastIndexOf(CharSequence cs, char c) {
        int len = length(cs);
        for (int pos = len - 1; pos >= 0; pos--) {
            char ch = cs.charAt(pos);
            if (ch == c) {
                return pos;
            }
        }

        return -1;
    }

    // a List would be better, but we want to be compatible with String.split(...)
    public static String[] split(String s, char ch) {
        if (isEmpty(s)) {
            return EMPTY_STRING_ARRAY;
        }

        int lastPos = 0;
        int curPos = s.indexOf(ch);
        if (curPos < 0) {
            return new String[] { s };
        }

        Collection<String> values = new LinkedList<>();
        do {
            String v = s.substring(lastPos, curPos);
            values.add(v);

            // skip separator
            lastPos = curPos + 1;
            if (lastPos >= s.length()) {
                break;
            }

            curPos = s.indexOf(ch, lastPos);
            if (curPos < lastPos) {
                break; // no more separators
            }
        } while (curPos < s.length());

        // check if any leftovers
        if (lastPos < s.length()) {
            String v = s.substring(lastPos);
            values.add(v);
        }

        return values.toArray(new String[values.size()]);
    }

    public static <T> String join(T[] values, char ch) {
        return join(isEmpty(values) ? Collections.<T> emptyList() : Arrays.asList(values), ch);
    }

    public static String join(Iterable<?> iter, char ch) {
        return join((iter == null) ? null : iter.iterator(), ch);
    }

    public static String join(Iterator<?> iter, char ch) {
        if ((iter == null) || (!iter.hasNext())) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        do { // we already asked hasNext...
            Object o = iter.next();
            if (sb.length() > 0) {
                sb.append(ch);
            }
            sb.append(Objects.toString(o));
        } while (iter.hasNext());

        return sb.toString();
    }

    public static <T> String join(T[] values, CharSequence sep) {
        return join(isEmpty(values) ? Collections.<T> emptyList() : Arrays.asList(values), sep);
    }

    public static String join(Iterable<?> iter, CharSequence sep) {
        return join((iter == null) ? null : iter.iterator(), sep);
    }

    public static String join(Iterator<?> iter, CharSequence sep) {
        if ((iter == null) || (!iter.hasNext())) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        do { // we already asked hasNext...
            Object o = iter.next();
            if (sb.length() > 0) {
                sb.append(sep);
            }
            sb.append(Objects.toString(o));
        } while (iter.hasNext());

        return sb.toString();
    }

    public static int size(Collection<?> c) {
        return (c == null) ? 0 : c.size();
    }

    public static boolean isEmpty(Collection<?> c) {
        return size(c) <= 0;
    }

    public static boolean isNotEmpty(Collection<?> c) {
        return !isEmpty(c);
    }

    /**
     *
     * @param  <T> Generic element type
     * @param  c1  First collection
     * @param  c2  Second collection
     * @return     {@code true} if the following holds:
     *             <UL>
     *             <LI>Same size - <B>Note:</B> {@code null} collections are consider equal to empty ones</LI>
     *
     *             <LI>First collection contains all elements of second one and vice versa</LI>
     *             </UL>
     */
    public static <T> boolean equals(Collection<T> c1, Collection<T> c2) {
        if (isEmpty(c1)) {
            return isEmpty(c2);
        } else if (isEmpty(c2)) {
            return false;
        }

        return (c1.size() == c2.size())
                && c1.containsAll(c2)
                && c2.containsAll(c1);
    }

    @SafeVarargs
    public static <T> int length(T... a) {
        return (a == null) ? 0 : a.length;
    }

    public static <T> boolean isEmpty(Iterable<? extends T> iter) {
        if (iter == null) {
            return true;
        } else if (iter instanceof Collection<?>) {
            return isEmpty((Collection<?>) iter);
        } else {
            return isEmpty(iter.iterator());
        }
    }

    public static <T> boolean isNotEmpty(Iterable<? extends T> iter) {
        return !isEmpty(iter);
    }

    public static <T> boolean isEmpty(Iterator<? extends T> iter) {
        return (iter == null) || (!iter.hasNext());
    }

    public static <T> boolean isNotEmpty(Iterator<? extends T> iter) {
        return !isEmpty(iter);
    }

    public static <T> boolean isEmpty(T[] a) {
        return length(a) <= 0;
    }

    public static int length(char[] chars) {
        return (chars == null) ? 0 : chars.length;
    }

    public static boolean isEmpty(char[] chars) {
        return length(chars) <= 0;
    }

    /**
     * Compares 2 character arrays - <B>Note:</B> {@code null} and empty are considered <U>equal</U>
     *
     * @param  c1 1st array
     * @param  c2 2nd array
     * @return    Negative is 1st array comes first in lexicographical order, positive if 2nd array comes first and zero
     *            if equal
     */
    public static int compare(char[] c1, char[] c2) {
        int l1 = length(c1);
        int l2 = length(c2);
        int cmpLen = Math.min(l1, l2);
        for (int index = 0; index < cmpLen; index++) {
            char c11 = c1[index];
            char c22 = c2[index];
            int nRes = Character.compare(c11, c22);
            if (nRes != 0) {
                return nRes;
            }
        }

        int nRes = Integer.compare(l1, l2);
        if (nRes != 0) {
            return nRes;
        }

        return 0;
    }

    @SafeVarargs // there is no EnumSet.of(...) so we have to provide our own
    public static <E extends Enum<E>> Set<E> of(E... values) {
        return of(isEmpty(values) ? Collections.emptySet() : Arrays.asList(values));
    }

    public static <E extends Enum<E>> Set<E> of(Collection<? extends E> values) {
        if (isEmpty(values)) {
            return Collections.emptySet();
        }

        Set<E> result = null;
        for (E v : values) {
            /*
             * A trick to compensate for the fact that we do not have the enum Class to invoke EnumSet.noneOf
             */
            if (result == null) {
                result = EnumSet.of(v);
            } else {
                result.add(v);
            }
        }

        return result;
    }

    public static <T> int findFirstDifferentValueIndex(List<? extends T> c1, List<? extends T> c2) {
        return findFirstDifferentValueIndex(c1, c2, UnaryEquator.defaultEquality());
    }

    public static <T> int findFirstDifferentValueIndex(
            List<? extends T> c1, List<? extends T> c2, UnaryEquator<? super T> equator) {
        Objects.requireNonNull(equator, "No equator provided");

        int l1 = size(c1);
        int l2 = size(c2);
        for (int index = 0, count = Math.min(l1, l2); index < count; index++) {
            T v1 = c1.get(index);
            T v2 = c2.get(index);
            if (!equator.test(v1, v2)) {
                return index;
            }
        }

        // all common length items are equal - check length
        if (l1 < l2) {
            return l1;
        } else if (l2 < l1) {
            return l2;
        } else {
            return -1;
        }
    }

    public static <T> int findFirstDifferentValueIndex(Iterable<? extends T> c1, Iterable<? extends T> c2) {
        return findFirstDifferentValueIndex(c1, c2, UnaryEquator.defaultEquality());
    }

    public static <T> int findFirstDifferentValueIndex(
            Iterable<? extends T> c1, Iterable<? extends T> c2, UnaryEquator<? super T> equator) {
        return findFirstDifferentValueIndex(iteratorOf(c1), iteratorOf(c2), equator);
    }

    public static <T> int findFirstDifferentValueIndex(Iterator<? extends T> i1, Iterator<? extends T> i2) {
        return findFirstDifferentValueIndex(i1, i2, UnaryEquator.defaultEquality());
    }

    public static <T> int findFirstDifferentValueIndex(
            Iterator<? extends T> i1, Iterator<? extends T> i2, UnaryEquator<? super T> equator) {
        Objects.requireNonNull(equator, "No equator provided");

        i1 = iteratorOf(i1);
        i2 = iteratorOf(i2);
        for (int index = 0;; index++) {
            if (i1.hasNext()) {
                if (i2.hasNext()) {
                    T v1 = i1.next();
                    T v2 = i2.next();
                    if (!equator.test(v1, v2)) {
                        return index;
                    }
                } else {
                    return index;
                }
            } else if (i2.hasNext()) {
                return index;
            } else {
                return -1; // neither has a next value - both exhausted at the same time
            }
        }
    }

    public static <T> boolean containsAny(
            Collection<? extends T> coll, Iterable<? extends T> values) {
        if (isEmpty(coll)) {
            return false;
        }

        for (T v : values) {
            if (coll.contains(v)) {
                return true;
            }
        }

        return false;
    }

    public static <T> void forEach(
            Iterable<? extends T> values, Consumer<? super T> consumer) {
        if (isNotEmpty(values)) {
            values.forEach(consumer);
        }
    }

    public static <T, U> List<U> map(
            Collection<? extends T> values, Function<? super T, ? extends U> mapper) {
        return stream(values).map(mapper).collect(Collectors.toList());
    }

    public static <T, U> NavigableSet<U> mapSort(
            Collection<? extends T> values, Function<? super T, ? extends U> mapper, Comparator<? super U> comparator) {
        return stream(values).map(mapper).collect(toSortedSet(comparator));
    }

    public static <T> Collector<T, ?, NavigableSet<T>> toSortedSet(Comparator<? super T> comparator) {
        return Collectors.toCollection(() -> new TreeSet<>(comparator));
    }

    public static <T> Stream<T> stream(Iterable<T> values) {
        if (isEmpty(values)) {
            return Stream.empty();
        } else if (values instanceof Collection<?>) {
            return ((Collection<T>) values).stream();
        } else {
            return StreamSupport.stream(values.spliterator(), false);
        }
    }

    @SafeVarargs
    public static <T> List<T> unmodifiableList(T... values) {
        return unmodifiableList(asList(values));
    }

    public static <T> List<T> unmodifiableList(Collection<? extends T> values) {
        if (isEmpty(values)) {
            return Collections.emptyList();
        } else {
            return Collections.unmodifiableList(new ArrayList<>(values));
        }
    }

    public static <T> List<T> unmodifiableList(Stream<T> values) {
        return unmodifiableList(values.collect(Collectors.toList()));
    }

    @SafeVarargs
    public static <T> List<T> asList(T... values) {
        return isEmpty(values) ? Collections.emptyList() : Arrays.asList(values);
    }

    @SafeVarargs
    public static <T> Set<T> asSet(T... values) {
        return new HashSet<>(asList(values));
    }

    @SafeVarargs
    public static <V extends Comparable<V>> NavigableSet<V> asSortedSet(V... values) {
        return asSortedSet(Comparator.naturalOrder(), values);
    }

    public static <V extends Comparable<V>> NavigableSet<V> asSortedSet(Collection<? extends V> values) {
        return asSortedSet(Comparator.naturalOrder(), values);
    }

    /**
     * @param  <V>    The element type
     * @param  comp   The (non-{@code null}) {@link Comparator} to use
     * @param  values The values to be added (ignored if {@code null})
     * @return        A {@link NavigableSet} containing the values (if any) sorted using the provided comparator
     */
    @SafeVarargs
    public static <V> NavigableSet<V> asSortedSet(Comparator<? super V> comp, V... values) {
        return asSortedSet(comp, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
    }

    /**
     * @param  <V>    The element type
     * @param  comp   The (non-{@code null}) {@link Comparator} to use
     * @param  values The values to be added (ignored if {@code null}/empty)
     * @return        A {@link NavigableSet} containing the values (if any) sorted using the provided comparator
     */
    public static <V> NavigableSet<V> asSortedSet(
            Comparator<? super V> comp, Collection<? extends V> values) {
        NavigableSet<V> set = new TreeSet<>(Objects.requireNonNull(comp, "No comparator"));
        if (size(values) > 0) {
            set.addAll(values);
        }
        return set;
    }

    @SafeVarargs
    public static <T> T findFirstMatchingMember(Predicate<? super T> acceptor, T... values) {
        return findFirstMatchingMember(acceptor,
                isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
    }

    public static <T> T findFirstMatchingMember(
            Predicate<? super T> acceptor, Collection<? extends T> values) {
        List<T> matches = selectMatchingMembers(acceptor, values);
        return GenericUtils.isEmpty(matches) ? null : matches.get(0);
    }

    /**
     * Returns a list of all the values that were accepted by a predicate
     *
     * @param  <T>      The type of value being evaluated
     * @param  acceptor The {@link Predicate} to consult whether a member is selected
     * @param  values   The values to be scanned
     * @return          A {@link List} of all the values that were accepted by the predicate
     */
    @SafeVarargs
    public static <T> List<T> selectMatchingMembers(Predicate<? super T> acceptor, T... values) {
        return selectMatchingMembers(acceptor,
                isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
    }

    /**
     * Returns a list of all the values that were accepted by a predicate
     *
     * @param  <T>      The type of value being evaluated
     * @param  acceptor The {@link Predicate} to consult whether a member is selected
     * @param  values   The values to be scanned
     * @return          A {@link List} of all the values that were accepted by the predicate
     */
    public static <T> List<T> selectMatchingMembers(
            Predicate<? super T> acceptor, Collection<? extends T> values) {
        return GenericUtils.stream(values)
                .filter(acceptor)
                .collect(Collectors.toList());
    }

    /**
     * @param  s The {@link CharSequence} to be checked
     * @return   If the sequence contains any of the {@link #QUOTES} on <U>both</U> ends, then they are stripped,
     *           otherwise nothing is done
     * @see      #stripDelimiters(CharSequence, char)
     */
    public static CharSequence stripQuotes(CharSequence s) {
        if (isEmpty(s)) {
            return s;
        }

        for (int index = 0; index < QUOTES.length(); index++) {
            char delim = QUOTES.charAt(index);
            CharSequence v = stripDelimiters(s, delim);
            if (v != s) { // if stripped one don't continue
                return v;
            }
        }

        return s;
    }

    /**
     * @param  s     The {@link CharSequence} to be checked
     * @param  delim The expected delimiter
     * @return       If the sequence contains the delimiter on <U>both</U> ends, then it is are stripped, otherwise
     *               nothing is done
     */
    public static CharSequence stripDelimiters(CharSequence s, char delim) {
        if (isEmpty(s) || (s.length() < 2)) {
            return s;
        }

        int lastPos = s.length() - 1;
        if ((s.charAt(0) != delim) || (s.charAt(lastPos) != delim)) {
            return s;
        } else {
            return s.subSequence(1, lastPos);
        }
    }

    /**
     * Wraps a value into a {@link Supplier}
     *
     * @param  <T>   Type of value being supplied
     * @param  value The value to be supplied
     * @return       The supplier wrapper
     */
    public static <T> Supplier<T> supplierOf(T value) {
        return () -> value;
    }

    /**
     * Resolves to an always non-{@code null} iterator
     *
     * @param  <T>      Type of value being iterated
     * @param  iterable The {@link Iterable} instance
     * @return          A non-{@code null} iterator which may be empty if no iterable instance or no iterator returned
     *                  from it
     * @see             #iteratorOf(Iterator)
     */
    public static <T> Iterator<T> iteratorOf(Iterable<T> iterable) {
        return iteratorOf((iterable == null) ? null : iterable.iterator());
    }

    /**
     * @param  <B> Generic base class
     * @param  <D> Generic child class
     * @return     An identity {@link Function} that returns its input child class as a base class
     */
    public static <B, D extends B> Function<D, B> downcast() {
        return t -> t;
    }

    /**
     * Returns the first element in iterable - it has some optimization for {@link List}-s {@link Deque}-s and
     * {@link SortedSet}s.
     *
     * @param  <T> Type of element
     * @param  it  The {@link Iterable} instance - ignored if {@code null}/empty
     * @return     first element by iteration or {@code null} if none available
     */
    public static <T> T head(Iterable<? extends T> it) {
        if (it == null) {
            return null;
        } else if (it instanceof Deque<?>) { // check before (!) instanceof List since LinkedList implements List
            Deque<? extends T> l = (Deque<? extends T>) it;
            return !l.isEmpty() ? l.getFirst() : null;
        } else if (it instanceof List<?>) {
            List<? extends T> l = (List<? extends T>) it;
            return !l.isEmpty() ? l.get(0) : null;
        } else if (it instanceof SortedSet<?>) {
            SortedSet<? extends T> s = (SortedSet<? extends T>) it;
            return !s.isEmpty() ? s.first() : null;
        } else {
            Iterator<? extends T> iter = it.iterator();
            return ((iter == null) || (!iter.hasNext())) ? null : iter.next();
        }
    }

    /**
     * Resolves to an always non-{@code null} iterator
     *
     * @param  <T>  Type of value being iterated
     * @param  iter The {@link Iterator} instance
     * @return      A non-{@code null} iterator which may be empty if no iterator instance
     * @see         Collections#emptyIterator()
     */
    public static <T> Iterator<T> iteratorOf(Iterator<T> iter) {
        return (iter == null) ? Collections.emptyIterator() : iter;
    }

    public static <U, V> Iterable<V> wrapIterable(
            Iterable<? extends U> iter, Function<? super U, ? extends V> mapper) {
        return () -> wrapIterator(iter, mapper);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <U, V> Iterator<V> wrapIterator(
            Iterable<? extends U> iter, Function<? super U, ? extends V> mapper) {
        return (Iterator) stream(iter).map(mapper).iterator();
    }

    public static <U, V> Iterator<V> wrapIterator(
            Iterator<? extends U> iter, Function<? super U, ? extends V> mapper) {
        Iterator<? extends U> iterator = iteratorOf(iter);
        return new Iterator<V>() {
            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public V next() {
                U value = iterator.next();
                return mapper.apply(value);
            }
        };
    }

    /**
     * @param  <T>    Generic return type
     * @param  values The source values - ignored if {@code null}
     * @param  type   The (never @code null) type of values to select - any value whose type is assignable to this type
     *                will be selected by the iterator.
     * @return        The first value that matches the specified type - {@code null} if none found
     */
    public static <T> T selectNextMatchingValue(Iterator<?> values, Class<T> type) {
        Objects.requireNonNull(type, "No type selector specified");
        if (values == null) {
            return null;
        }

        while (values.hasNext()) {
            Object o = values.next();
            if (o == null) {
                continue;
            }

            Class<?> t = o.getClass();
            if (type.isAssignableFrom(t)) {
                return type.cast(o);
            }
        }

        return null;
    }

    /**
     * Wraps a group of {@link Supplier}s of {@link Iterable} instances into a &quot;unified&quot; {@link Iterable} of
     * their values, in the same order as the suppliers - i.e., once the values from a specific supplier are exhausted,
     * the next one is consulted, and so on, until all suppliers have been consulted
     *
     * @param  <T>       Type of value being iterated
     * @param  providers The providers - ignored if {@code null} (i.e., return an empty iterable instance)
     * @return           The wrapping instance
     */
    public static <T> Iterable<T> multiIterableSuppliers(
            Iterable<? extends Supplier<? extends Iterable<? extends T>>> providers) {
        return () -> stream(providers).<T> flatMap(s -> stream(s.get())).map(Function.identity()).iterator();
    }

    /**
     * The delegate Suppliers get() method is called exactly once and the result is cached.
     *
     * @param  <T>      Generic type of supplied value
     * @param  delegate The actual Supplier
     * @return          The memoized Supplier
     */
    public static <T> Supplier<T> memoizeLock(Supplier<? extends T> delegate) {
        AtomicReference<T> value = new AtomicReference<>();
        return () -> {
            T val = value.get();
            if (val == null) {
                synchronized (value) {
                    val = value.get();
                    if (val == null) {
                        val = Objects.requireNonNull(delegate.get());
                        value.set(val);
                    }
                }
            }
            return val;
        };
    }

    /**
     * Check if a duration is positive
     *
     * @param  d the duration
     * @return   <code>true</code> if the duration is greater than zero
     */
    public static boolean isPositive(Duration d) {
        return !isNegativeOrNull(d);
    }

    /**
     * Check if a duration is negative or zero
     *
     * @param  d the duration
     * @return   <code>true</code> if the duration is negative or zero
     */
    public static boolean isNegativeOrNull(Duration d) {
        return d.isNegative() || d.isZero();
    }
}
