package mariaJava;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;

public class TutorialsPoint {
	public void allTutorialsPoint(TutorialsPoint tutorialsPoint) {
		testSort();
		testLambdas();
		testForEach();
		testPredicate();
	}
	
//------------------
	public void testSort() {
		System.out.println("-- Test Collections.sort:");
		List<String> names1 = new ArrayList<String>();
		names1.add("Maria");
		names1.add("Klara");

		List<String> names2 = new ArrayList<String>();
		names2.add("Jacob");
		names2.add("Erik");

		System.out.println("Sotring using java7 syntax:");
		sortUsingJava7(names1);
		System.out.println(names1);

		System.out.println("Sotring using java8 syntax:");
		sortUsingJava8(names2);
		System.out.println(names2);
	}

	private void sortUsingJava8(List<String> names) {
		Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
	}

	private void sortUsingJava7(List<String> names) {

		Collections.sort(names, new Comparator<String>() {

			@Override
			public int compare(String s1, String s2) {
				return s1.compareTo(s2);
			}
		});
	}
//--------------------
	
	public void testLambdas() {
		System.out.println("-- Test lambdas:");
		
		//With type declaration
		MathOperation addition = (int a, int b) -> a + b;
		//without tyoe declaration
		MathOperation substraction = (a,b) -> a-b;
		//with return statements and curly braces
		MathOperation multiplication = (int a, int b) -> {return a*b;};
		//without return statement and without curly braces
		MathOperation division = (int a, int b) -> a/b;
	
		System.out.println("10+5=" + operate(10, 5, addition));
		System.out.println("10+5=" + operate(10, 5, substraction));
		System.out.println("10+5=" + operate(10, 5, multiplication));
		System.out.println("10+5=" + operate(10, 5, division));
		
		//Without parenthesis:
		GreetingService greetService1 = message -> System.out.println("Hello " + message);
		
		//With parenthesis:
		GreetingService greetService2 = (message) -> System.out.println("Hello " + message);
		
		greetService1.sayMessage("Maria1");
		greetService2.sayMessage("Maria2");
	}
	
	private int operate(int a, int b, MathOperation mathOperation) {
		return mathOperation.operation(a, b);
	}

	//-- My own functional interfaces:
	interface MathOperation {
		int operation(int a, int b); //The implementations are in the lambdas above!
	}
	
	interface GreetingService {
		void sayMessage(String message);
	}
	
//--------------------

	public void testForEach() {
		System.out.println("-- Test for each:");
		List<String> names = new ArrayList<String>();
		names.add("Maria");
		names.add("Jacob");
		names.add("Klara");
		names.add("Erik");
		
		names.forEach(System.out::println);
	}
	
//---------------------
	public void testPredicate() {
		System.out.println("-- Test predicate");
		
		List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
		
		//pass n as parameter (n is always true)
		System.out.println("Print all numbers");
		eval(list, n -> true);
		
		System.out.println("Print even numbers:");
		eval(list, n -> n%2==0);
		
		System.out.println("Print numbers greater than 6");
		eval(list, n -> n>6);
	}
	
	public void eval(List<Integer> list, Predicate<Integer> predicate) {
		for(Integer n: list) {
			if(predicate.test(n)) {
				System.out.println(n+ " ");
			}
		}
	}
	
	//----
	
}
