/*
 * 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.geode.internal.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.geode.internal.lang.Filter;

/**
 * The CollectionUtils class is a utility class for working with the Java Collections framework of
 * classes, data structures and algorithms.
 * <p/>
 *
 * @see org.apache.geode.internal.lang.Filter
 * @see java.util.Arrays
 * @see java.util.Collection
 * @see java.util.Collections
 * @see java.util.Iterator
 * @see java.util.List
 * @see java.util.Map
 * @see java.util.Set
 * @since GemFire 7.0
 */
public abstract class CollectionUtils {

  /**
   * Returns the specified array as a List of elements.
   * <p/>
   *
   * @param <T> the class type of the elements in the array.
   * @param array the object array of elements to convert to a List.
   * @return a List of elements contained in the specified array.
   * @see java.util.Arrays#asList(Object[])
   */
  @SafeVarargs
  public static <T> List<T> asList(final T... array) {
    List<T> arrayList = new ArrayList<T>(array.length);
    Collections.addAll(arrayList, array);
    return arrayList;
  }

  /**
   * Returns the specified array as a Set of elements.
   * <p/>
   *
   * @param <T> the class type of the elements in the array.
   * @param array the object array of elements to convert to a Set.
   * @return a Set of elements contained in the specified array.
   * @see java.util.Arrays#asList(Object[])
   */
  @SafeVarargs
  public static <T> Set<T> asSet(final T... array) {
    Set<T> arraySet = new HashSet<T>(array.length);
    Collections.addAll(arraySet, array);
    return arraySet;
  }

  /**
   * Creates an Properties object initialized with the value from the given Map.
   * <p>
   *
   * @param map the Map supply the keys and value for the Properties object.
   * @return a Properties object initialized with the key and value from the Map.
   * @see java.util.Map
   * @see java.util.Properties
   */
  public static Properties createProperties(final Map<String, String> map) {
    Properties properties = new Properties();

    if (!(map == null || map.isEmpty())) {
      for (Entry<String, String> entry : map.entrySet()) {
        properties.setProperty(entry.getKey(), entry.getValue());
      }
    }

    return properties;
  }

  /**
   * Null-safe implementation for method invocations that return a List Collection. If the returned
   * List is null, then this method will return an empty List in it's place.
   * <p/>
   *
   * @param <T> the class type of the List's elements.
   * @param list the target List to verify as not null.
   * @return the specified List if not null otherwise return an empty List.
   */
  public static <T> List<T> emptyList(final List<T> list) {
    return (list != null ? list : Collections.<T>emptyList());
  }

  /**
   * Null-safe implementation for method invocations that return a Set Collection. If the returned
   * Set is null, then this method will return an empty Set in it's place.
   * <p/>
   *
   * @param <T> the class type of the Set's elements.
   * @param set the target Set to verify as not null.
   * @return the specified Set if not null otherwise return an empty Set.
   */
  public static <T> Set<T> emptySet(final Set<T> set) {
    return (set != null ? set : Collections.<T>emptySet());
  }

  /**
   * Iterates the Collection and finds all object elements that match the Filter criteria.
   * <p/>
   *
   * @param <T> the class type of the Collection elements.
   * @param collection the Collection of elements to iterate and filter.
   * @param filter the Filter applied to the Collection of elements in search of all matching
   *        elements.
   * @return a List of elements from the Collection matching the criteria of the Filter in the order
   *         in which they were found. If no elements match the Filter criteria, then an empty List
   *         is returned.
   */
  public static <T> List<T> findAll(final Collection<T> collection, final Filter<T> filter) {
    final List<T> matches = new ArrayList<T>(collection.size());

    for (final T element : collection) {
      if (filter.accept(element)) {
        matches.add(element);
      }
    }

    return matches;
  }

  /**
   * Iterates the Collection and finds all object elements that match the Filter criteria.
   * <p/>
   *
   * @param <T> the class type of the Collection elements.
   * @param collection the Collection of elements to iterate and filter.
   * @param filter the Filter applied to the Collection of elements in search of the matching
   *        element.
   * @return a single element from the Collection that match the criteria of the Filter. If multiple
   *         elements match the Filter criteria, then this method will return the first one. If no
   *         element of the Collection matches the criteria of the Filter, then this method returns
   *         null.
   */
  public static <T> T findBy(final Collection<T> collection, final Filter<T> filter) {
    for (T element : collection) {
      if (filter.accept(element)) {
        return element;
      }
    }

    return null;
  }

  /**
   * Removes keys from the Map based on a Filter.
   * <p/>
   *
   * @param <K> the Class type of the key.
   * @param <V> the Class type of the value.
   * @param map the Map from which to remove key-value pairs based on a Filter.
   * @param filter the Filter to apply to the Map entries to ascertain their "value".
   * @return the Map with entries filtered by the specified Filter.
   * @see java.util.Map
   * @see java.util.Map.Entry
   * @see org.apache.geode.internal.lang.Filter
   */
  public static <K, V> Map<K, V> removeKeys(final Map<K, V> map,
      final Filter<Map.Entry<K, V>> filter) {
    for (final Iterator<Map.Entry<K, V>> mapEntries = map.entrySet().iterator(); mapEntries
        .hasNext();) {
      if (!filter.accept(mapEntries.next())) {
        mapEntries.remove();
      }
    }

    return map;
  }

  /**
   * Removes keys with null values in the Map.
   * <p/>
   *
   * @param map the Map from which to remove null key-value pairs.
   * @return the Map without any null keys or values.
   * @see #removeKeys
   * @see java.util.Map
   */
  public static <K, V> Map<K, V> removeKeysWithNullValues(final Map<K, V> map) {
    return removeKeys(map, new Filter<Map.Entry<K, V>>() {
      @Override
      public boolean accept(final Map.Entry<K, V> entry) {
        return (entry.getValue() != null);
      }
    });
  }

  /**
   * Add all elements of an {@link Enumeration} to a {@link Collection}.
   *
   * @param collection to add from enumeration.
   * @param enumeration to add to collection.
   * @return true if collection is modified, otherwise false.
   * @since GemFire 8.1
   * @see Collection#addAll(Collection)
   */
  public static <T> boolean addAll(final Collection<T> collection,
      final Enumeration<T> enumeration) {
    if (null == enumeration) {
      return false;
    }

    boolean modified = false;
    while (enumeration.hasMoreElements()) {
      modified |= collection.add(enumeration.nextElement());
    }
    return modified;
  }

  /**
   * Construct a new unmodifiable {@link Iterable} backed by the supplied <code>iterable</code>.
   *
   * {@link Iterable#iterator()} will return an umodifiable {@link Iterator} on which calling
   * {@link Iterator#remove()} will throw {@link UnsupportedOperationException}.
   *
   * @param iterable to wrap as unmodifiable
   * @return unmodifiable {@link Iterable}
   * @since GemFire 8.1
   */
  public static <T> Iterable<T> unmodifiableIterable(final Iterable<T> iterable) {
    return new UnmodifiableIterable<T>(iterable);
  }

  /**
   * Unmodifiable {@link Iterable} in the style of
   * {@link Collections#unmodifiableCollection(Collection)}.
   *
   *
   * @since GemFire 8.1
   */
  private static class UnmodifiableIterable<T> implements Iterable<T> {

    private final Iterable<T> iterable;

    private UnmodifiableIterable(final Iterable<T> iterable) {
      this.iterable = iterable;
    }

    @Override
    public Iterator<T> iterator() {
      return new Iterator<T>() {
        private final Iterator<T> iterator = iterable.iterator();

        @Override
        public boolean hasNext() {
          return iterator.hasNext();
        }

        @Override
        public T next() {
          return iterator.next();
        }

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