// ***************************************************************************************************************************
// * 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.juneau.internal;

import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ThrowableUtils.*;

import java.lang.reflect.*;
import java.util.*;

/**
 * Quick and dirty utilities for working with arrays.
 */
public final class ArrayUtils {

	/**
	 * Appends one or more elements to an array.
	 *
	 * @param <T> The element type.
	 * @param array The array to append to.
	 * @param newElements The new elements to append to the array.
	 * @return A new array with the specified elements appended.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] append(T[] array, T...newElements) {
		if (array == null)
			return newElements;
		if (newElements.length == 0)
			return array;
		T[] a = (T[])Array.newInstance(array.getClass().getComponentType(), array.length + newElements.length);
		for (int i = 0; i < array.length; i++)
			a[i] = array[i];
		for (int i = 0; i < newElements.length; i++)
			a[i+array.length] = newElements[i];
		return a;
	}

	/**
	 * Appends one or more elements to an array.
	 *
	 * @param <T> The element type.
	 * @param array The array to append to.
	 * @param newElements The new elements to append to the array.
	 * @return A new array with the specified elements appended.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] append(T[] array, Collection<T> newElements) {
		assertFieldNotNull(array, "array");
		if (newElements.size() == 0)
			return array;
		T[] a = (T[])Array.newInstance(array.getClass().getComponentType(), array.length + newElements.size());
		for (int i = 0; i < array.length; i++)
			a[i] = array[i];
		int l = array.length;
		for (T t : newElements)
			a[l++] = t;
		return a;
	}

	/**
	 * Combine an arbitrary number of arrays into a single array.
	 *
	 * @param arrays Collection of arrays to combine.
	 * @return A new combined array, or <jk>null</jk> if all arrays are <jk>null</jk>.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] combine(T[]...arrays) {
		assertFieldNotNull(arrays, "arrays");
		int l = 0;
		T[] a1 = null;
		for (T[] a : arrays) {
			if (a1 == null && a != null)
				a1 = a;
			l += (a == null ? 0 : a.length);
		}
		if (a1 == null)
			return null;
		T[] a = (T[])Array.newInstance(a1.getClass().getComponentType(), l);
		int i = 0;
		for (T[] aa : arrays)
			if (aa != null)
				for (T t : aa)
					a[i++] = t;
		return a;
	}

	/**
	 * Creates a new array with reversed entries.
	 *
	 * @param <T> The class type of the array.
	 * @param array The array to reverse.
	 * @return A new array with reversed entries, or <jk>null</jk> if the array was <jk>null</jk>.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] reverse(T[] array) {
		if (array == null)
			return null;
		Class<T> c = (Class<T>)array.getClass().getComponentType();
		T[] a2 = (T[])Array.newInstance(c, array.length);
		for (int i = 0; i < array.length; i++)
			a2[a2.length-i-1] = array[i];
		return a2;
	}

	/**
	 * Sorts the elements in an array without creating a new array.
	 *
	 * @param array The array to sort.
	 * @return The same array.
	 */
	public static <T> T[] reverseInline(T[] array) {
		if (array == null)
			return null;
		T t;
		for (int i = 0, j = array.length-1; i < j; i++, j--) {
			t = array[i];
			array[i] = array[j];
			array[j] = t;
		}
		return array;
	}

	/**
	 * Converts the specified array to a <c>Set</c>.
	 *
	 * <p>
	 * The order of the entries in the set are the same as the array.
	 *
	 * @param <T> The entry type of the array.
	 * @param array The array being wrapped in a <c>Set</c> interface.
	 * @return The new set.
	 */
	public static <T> Set<T> asSet(final T[] array) {
		assertFieldNotNull(array, "array");
		return new AbstractSet<T>() {

			@Override /* Set */
			public Iterator<T> iterator() {
				return new Iterator<T>() {
					int i = 0;

					@Override /* Iterator */
					public boolean hasNext() {
						return i < array.length;
					}

					@Override /* Iterator */
					public T next() {
						if (i >= array.length)
							throw new NoSuchElementException();
						T t = array[i];
						i++;
						return t;
					}

					@Override /* Iterator */
					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}

			@Override /* Set */
			public int size() {
				return array.length;
			}
		};
	}

	/**
	 * Returns an iterator against an array.
	 *
	 * <p>
	 * This works with any array type (e.g. <c>String[]</c>, <c>Object[]</c>,
	 * <code><jk>int</jk>[]</code>, etc...).
	 *
	 * @param array The array to create an iterator over.
	 * @return An iterator over the specified array.
	 */
	public static Iterator<Object> iterator(final Object array) {
		return new Iterator<Object>() {
			int i = 0;
			int length = array == null ? 0 : Array.getLength(array);

			@Override /* Iterator */
			public boolean hasNext() {
				return i < length;
			}

			@Override /* Iterator */
			public Object next() {
				if (i >= length)
					throw new NoSuchElementException();
				return Array.get(array, i++);
			}

			@Override /* Iterator */
			public void remove() {
				throw new UnsupportedOperationException();
			}
		};
	}

	/**
	 * Converts the specified collection to an array.
	 *
	 * <p>
	 * Works on both object and primitive arrays.
	 *
	 * @param c The collection to convert to an array.
	 * @param componentType The component type of the collection.
	 * @return A new array.
	 */
	public static <T> Object toArray(Collection<?> c, Class<T> componentType) {
		Object a = Array.newInstance(componentType, c.size());
		Iterator<?> it = c.iterator();
		int i = 0;
		while (it.hasNext())
			Array.set(a, i++, it.next());
		return a;
	}

	/**
	 * Returns <jk>true</jk> if the specified object is an array.
	 *
	 * @param array The array to test.
	 * @return <jk>true</jk> if the specified object is an array.
	 */
	public static boolean isArray(Object array) {
		return array != null && array.getClass().isArray();
	}

	/**
	 * Converts the specified array to an <c>ArrayList</c>
	 *
	 * @param array The array to convert.
	 * @param componentType
	 * 	The type of objects in the array.
	 * 	It must match the actual component type in the array.
	 * @return A new {@link ArrayList}
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> toList(Object array, Class<T> componentType) {
		List<T> l = new ArrayList<>(Array.getLength(array));
		for (int i = 0; i < Array.getLength(array); i++)
			l.add((T)Array.get(array, i));
		return l;
	}

	/**
	 * Shortcut for calling <c>myList.toArray(new T[myList.size()]);</c>
	 *
	 * @param c The collection being converted to an array.
	 * @param componentType The component type of the array.
	 * @return The collection converted to an array.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] toObjectArray(Collection<?> c, Class<T> componentType) {
		Object a = Array.newInstance(componentType, c.size());
		Iterator<?> it = c.iterator();
		int i = 0;
		while (it.hasNext())
			Array.set(a, i++, it.next());
		return (T[])a;
	}

	/**
	 * Copies the specified array into the specified list.
	 *
	 * <p>
	 * Works on both object and primitive arrays.
	 *
	 * @param array The array to copy into a list.
	 * @param list The list to copy the values into.
	 * @return The same list passed in.
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	public static List copyToList(Object array, List list) {
		if (array != null) {
			int length = Array.getLength(array);
			for (int i = 0; i < length; i++)
				list.add(Array.get(array, i));
		}
		return list;
	}

	/**
	 * Returns <jk>true</jk> if the specified array contains the specified element using the {@link Object#equals(Object)}
	 * method.
	 *
	 * @param element The element to check for.
	 * @param array The array to check.
	 * @return
	 * 	<jk>true</jk> if the specified array contains the specified element,
	 * 	<jk>false</jk> if the array or element is <jk>null</jk>.
	 */
	public static <T> boolean contains(T element, T[] array) {
		return indexOf(element, array) != -1;
	}

	/**
	 * Returns <jk>true</jk> if the specified array contains the specified integer
	 *
	 * @param element The element to check for.
	 * @param array The array to check.
	 * @return
	 * 	<jk>true</jk> if the specified array contains the specified element,
	 * 	<jk>false</jk> if the array or element is <jk>null</jk>.
	 */
	public static boolean contains(int element, int[] array) {
		if (array != null)
			for (int i : array)
				if (element == i)
					return true;
		return false;
	}

	/**
	 * Returns the index position of the element in the specified array using the {@link Object#equals(Object)} method.
	 *
	 * @param element The element to check for.
	 * @param array The array to check.
	 * @return
	 * 	The index position of the element in the specified array, or <c>-1</c> if the array doesn't contain the
	 * 	element, or the array or element is <jk>null</jk>.
	 */
	public static <T> int indexOf(T element, T[] array) {
		if (element == null)
			return -1;
		if (array == null)
			return -1;
		for (int i = 0; i < array.length; i++)
			if (element.equals(array[i]))
				return i;
		return -1;
	}

	/**
	 * Returns <jk>true</jk> if the specified array contains the specified element using the {@link String#equals(Object)}
	 * method.
	 *
	 * @param element The element to check for.
	 * @param array The array to check.
	 * @return
	 * 	<jk>true</jk> if the specified array contains the specified element,
	 * 	<jk>false</jk> if the array or element is <jk>null</jk>.
	 */
	public static boolean contains(String element, String[] array) {
		return indexOf(element, array) != -1;
	}

	/**
	 * Returns the index position of the element in the specified array using the {@link String#equals(Object)} method.
	 *
	 * @param element The element to check for.
	 * @param array The array to check.
	 * @return
	 * 	The index position of the element in the specified array, or
	 * 	<c>-1</c> if the array doesn't contain the element, or the array or element is <jk>null</jk>.
	 */
	public static int indexOf(String element, String[] array) {
		if (element == null)
			return -1;
		if (array == null)
			return -1;
		for (int i = 0; i < array.length; i++)
			if (element.equals(array[i]))
				return i;
		return -1;
	}

	/**
	 * Converts a primitive wrapper array (e.g. <c>Integer[]</c>) to a primitive array (e.g. <code><jk>int</jk>[]</code>).
	 *
	 * @param o The array to convert.  Must be a primitive wrapper array.
	 * @return A new array.
	 * @throws IllegalArgumentException If object is not a wrapper object array.
	 */
	public static Object toPrimitiveArray(Object o) {
		Class<?> c = o.getClass();
		if (! c.isArray())
			throw new IllegalArgumentException("Cannot pass non-array objects to toPrimitiveArray()");
		int l = Array.getLength(o);
		Class<?> tc = getClassInfo(c.getComponentType()).getPrimitiveForWrapper();
		if (tc == null)
			throw new IllegalArgumentException("Array type is not a primitive wrapper array.");
		Object a = Array.newInstance(tc, l);
		for (int i = 0; i < l; i++)
			Array.set(a, i, Array.get(o, i));
		return a;
	}

	/**
	 * Converts an Iterable to a list.
	 *
	 * @param i The iterable to convert.
	 * @return A new list of objects copied from the iterable.
	 */
	public static List<?> toList(Iterable<?> i) {
		List<Object> l = new ArrayList<>();
		Iterator<?> i2 = i.iterator();
		while (i2.hasNext())
			l.add(i2.next());
		return l;
	}

	/**
	 * Returns the first object in the specified collection or array.
	 *
	 * @param val The collection or array object.
	 * @return
	 * 	The first object, or <jk>null</jk> if the collection or array is empty or <jk>null</jk> or the value
	 * 	isn't a collection or array.
	 */
	public static Object getFirst(Object val) {
		if (val != null) {
			if (val instanceof Collection) {
				Collection<?> c = (Collection<?>)val;
				if (c.isEmpty())
					return null;
				return c.iterator().next();
			}
			if (val.getClass().isArray())
				return Array.getLength(val) == 0 ? null : Array.get(val, 0);
		}
		return null;
	}

	/**
	 * Converts the specified collection to an array of strings.
	 *
	 * <p>
	 * Entries are converted to strings using {@link #toString()}.
	 * <jk>null</jk> values remain <jk>null</jk>.
	 *
	 * @param c The collection to convert.
	 * @return The collection as a string array.
	 */
	public static String[] toStringArray(Collection<?> c) {
		String[] r = new String[c.size()];
		int i = 0;
		for (Object o : c)
			r[i++] = stringify(o);
		return r;
	}

	/**
	 * Returns <jk>true</jk> if the following sorted arrays are equals.
	 *
	 * @param a1 Array #1.
	 * @param a2 Array #2.
	 * @return <jk>true</jk> if the following sorted arrays are equals.
	 */
	public static boolean equals(String[] a1, String[] a2) {
		if (a1.length != a2.length)
			return false;
		for (int i = 0; i < a1.length; i++)
			if (! StringUtils.isEquals(a1[i], a2[i]))
				return false;
		return true;
	}

	/**
	 * Converts a collection to an array containing the elements in reversed order.
	 *
	 * @param c The component type of the array.
	 * @param l
	 * 	The collection to convert.
	 * 	<br>The collection is not modified.
	 * @return
	 * 	A new array, or <jk>null</jk> if the collection was <jk>null</jk>.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] toReverseArray(Class<T> c, Collection<T> l) {
		if (l == null)
			return null;
		Object a = Array.newInstance(c, l.size());
		Iterator<T> i = l.iterator();
		int j = l.size();
		while (i.hasNext())
			Array.set(a, --j, i.next());
		return (T[])a;
	}

	/**
	 * Removes the specified element from the specified array.
	 *
	 * @param element The element to remove from the array.
	 * @param array The array to remove the element from.
	 * @return A new array with the element removed, or the original array if the array did not contain the element.
	 */
	public static Object[] remove(Object element, Object[] array) {
		if (! contains(element, array))
			return array;
		List<Object> l = new ArrayList<>(array.length);
		for (Object o2 : array) {
			if (! element.equals(o2))
				l.add(o2);
		}
		return l.toArray(new Object[l.size()]);
	}
}
