/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.collection;

import java.util.Arrays;
import java.util.Set;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;
import net.ranides.assira.collection.iterators.IntIterator;
import net.ranides.assira.collection.iterators.IntIteratorUtils;
import net.ranides.assira.collection.iterators.IteratorUtils;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class IntCollectionUtils {
	
	private IntCollectionUtils() {
		/* utility class */
	}
	
	public static int first(IntCollection values) {
		return IntIteratorUtils.first(values.iterator());
	}
	
	public static int first(IntCollection values, IntPredicate predicate) {
		return IntIteratorUtils.first(values.iterator(), predicate);
	}
	
	public static int last(IntCollection values) {
		return IntIteratorUtils.last(values.iterator());
	}
	
	public static int last(IntCollection values, IntPredicate predicate) {
		return IntIteratorUtils.last(values.iterator(), predicate);
	}
	
	public static IntCollection filter(IntCollection values, IntPredicate predicate) {
		return new AIntCollection() {
			@Override
			public IntIterator iterator() {
				return IntIteratorUtils.filter(values.iterator(), predicate);
			}

			@Override
			public int size() {
				return IntIteratorUtils.size(iterator());
			}

			@Override
			public boolean contains(int k) {
				return values.contains(k) && predicate.test(k);
			}
		};
	}
	
    public static <S,T> IntCollection map(IntCollection values, IntUnaryOperator function) {
        return new AIntCollection() {
			@Override
			public int size() {
				return values.size();
			}
			@Override
			public IntIterator iterator() {
				return IntIteratorUtils.map(values.iterator(), function);
			}
		};
    }

	public static boolean equivalent(IntCollection a, IntCollection b) {
		if( a.size() != b.size() ){
            return false;
        }
		// Set powinien oferować dobrą implementację funkcji containsAll
		if(a instanceof Set<?>) {
			return a.containsAll(b);
		}
		if(b instanceof Set<?>) {
			return b.containsAll(a);
		}
		
        // najpierw spróbujmy tak sprawdzić - takie porównanie powinno być względnie tanie
        // (złożoność O(N)) w porówaniu do następnej metody
        if( a.equals(b) || b.equals(a) ) {
            return true;
        }
		
        // dużo kopiowania, na dodatek mamy sortowanie, czyli złożoność
        // na pamięć O(N) oraz operacje O(N*log(N)) + O(N)
        int[] asort = a.toIntArray();
        int[] bsort = b.toIntArray();
        Arrays.sort(asort);
        Arrays.sort(bsort);
        return Arrays.equals(asort, bsort);
	}
	
}
