package rozwiazania_zadan.r2.z2_funkcje_na_tablicach;

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalInt;
import java.util.function.IntPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/** Ta wersja wykorzystuje strumienie (od Java 8) i gotowe rozwiązania, jeśli są dostępne. */
public class WersjaStrumieniowa {

	// Tu i w kilku dalej zmieniam typ na OptionalInt, bo to bardziej pasuje do nowoczesnego stylu niż Integer.
	static OptionalInt max(int[] t) {
		return IntStream.of(t).max();
	}
	
	static OptionalInt min(int[] t) {
		return IntStream.of(t).min();
	}
	
	static Integer min_v2(int[] t) {
		// Gdybyśmy bardzo chcieli zwrócić Integer, a nie OptionalInt
		OptionalInt opt = IntStream.of(t).min();
		if(opt.isPresent()) {
			return opt.getAsInt();
		} else {
			return null;
		}
	}
	
	static int roznicaMinMax(int[] t) {
		return max(t).orElse(0) - min(t).orElse(0);
	}
	

	static void wypiszWieksze(int[] t, int x) {
		IntStream.of(t)
			.filter(e -> e > x)
			.forEachOrdered(e -> System.out.print(e + ", "));
		System.out.println();
	}
	
	static OptionalInt pierwszaWieksza(int[] t, int x) {
		return IntStream.of(t)
			.filter(e -> e > x)
			.findFirst();
	}
	
	static int sumaWiekszych(int[] t, int x) {
		return IntStream.of(t)
				.filter(e -> e > x)
				.sum();
	}
	
	static long ileWiekszych(int[] t, int x) {
		return IntStream.of(t)
				.filter(e -> e > x)
				.count();
	}
	
	// przykłady z podzielnością wyszłyby bardzo podobne do 4 powyższych, dlatego wprowadzam pewne urozmaicenia
	
	private static IntPredicate jestPodzielnaPrzez(int x) {
		return (int e) -> e % x == 0;
	}

	static void wypiszPodzielne(int[] t, int x) {
		IntStream.of(t)
				.filter(jestPodzielnaPrzez(x))
				.forEachOrdered(System.out::println);
	}
	
	static OptionalInt pierwszaPodzielna(int[] t, int x) {
		return IntStream.of(t)
				.filter(jestPodzielnaPrzez(x))
				.findFirst();
	}
	
	static int sumaPodzielnych(int[] t, int x) {
		return IntStream.of(t)
				.filter(jestPodzielnaPrzez(x))
				.reduce(0, (a, e) -> a+e); // istnieje też sum
	}
	
	static int ilePodzielnych(int[] t, int x) {
		return IntStream.of(t)
				.filter(jestPodzielnaPrzez(x))
				.reduce(0, (a, e) -> a+1); // istnieje też count
	}
	
	
	static OptionalInt znajdzWspolny(int[] t1, int[] t2) {
		return IntStream.of(t1)
				.flatMap(e1 -> IntStream.of(t2).filter(e2 -> e1 == e2))
				.findAny();
	}
	
	static List<Integer> wszystkieWspolne(int[] t1, int[] t2) {
		return IntStream.of(t1)
				.flatMap(e1 -> IntStream.of(t2).filter(e2 -> e1 == e2))
				.boxed()
				.collect(Collectors.toList());
	}
}
