package info.schleichardt.training.java8.lecture2;

import java.security.MessageDigest;
import java.util.List;

import static java.util.Arrays.asList;

public class P1_FunctionalInterfaces {
    /*
     see https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html

     => functional interfaces have one abstract method, default methods are not abstract

     example:
     */

    @FunctionalInterface//compile checks if requirement of one abstract method is met
    public interface HashFunction {
        byte[] hash(final String input) throws Exception;
    }

    @FunctionalInterface
    public interface Whatever<V> {
        V aMethod();//one abstract method

        //impl method
        default List<V> anotherMethod() {
            return asList(aMethod(), aMethod());
        }
    }

    //two abstract methods
    public interface NotAFunctionalInterface<V> {
        V aMethod();
        List<V> anotherMethod();
    }

    /*
    Functional interfaces can be implemented and used the classic way:
     */
    class Md5HashFunction implements HashFunction {
        @Override
        public byte[] hash(final String input)  throws Exception {
            return MessageDigest.getInstance("MD5").digest(input.getBytes());
        }
    }

    class ClassicMd5HashFunctionUser {
        void demo() throws Exception {
            final HashFunction hashFunction = new Md5HashFunction();
            final byte[] bytes = hashFunction.hash("hello");
        }
    }

    class AnonymousClassHashFunctionUser {
        void demo() throws Exception {
            final HashFunction hashFunction = new HashFunction() {
                @Override
                public byte[] hash(final String input) throws Exception {
                    return MessageDigest.getInstance("SHA1").digest(input.getBytes());
                }
            };
            final byte[] bytes = hashFunction.hash("hello");
        }
    }

    /** Java 8 enables to use lambda functions: */

    class LambdaHashFunctionUser {
        void demo() throws Exception {
            final HashFunction hashFunction = (final String input) -> MessageDigest.getInstance("SHA2").digest(input.getBytes());
            final byte[] bytes = hashFunction.hash("hello");
        }
    }

    class UseInferenceAndConvention {
        void demo() throws Exception {
            final HashFunction hashFunction = input -> MessageDigest.getInstance("SHA12").digest(input.getBytes());
            final byte[] bytes = hashFunction.hash("hello");
        }
    }

    class Blocks {
        void demo() throws Exception {
            final HashFunction hashFunction = input -> {//parenthesis
                final MessageDigest sha12 = MessageDigest.getInstance("SHA12");
                return sha12.digest(input.getBytes());//return statement
            };
            final byte[] bytes = hashFunction.hash("hello");
        }
    }

    class MultipleParameters {



        void demo() throws Exception {
            final HashFunction hashFunction = input -> {//parenthesis
                final MessageDigest sha12 = MessageDigest.getInstance("SHA12");
                return sha12.digest(input.getBytes());//return statement
            };
            final byte[] bytes = hashFunction.hash("hello");
        }
    }
}
@@ -1991,24 +1991,31 @@
 ns: */%0A%0A    
+static 
 class Lambda
@@ -2280,24 +2280,31 @@
 %0A    %7D%0A%0A    
+static 
 class UseInf
@@ -2558,24 +2558,31 @@
 %0A    %7D%0A%0A    
+static 
 class Blocks
@@ -2939,24 +2939,31 @@
 %0A    %7D%0A%0A    
+static 
 class Multip
@@ -2981,19 +2981,16 @@
 s %7B%0A
-%0A%0A%0A
         
 void
@@ -2989,186 +2989,85 @@
     
-void demo() throws Exception %7B%0A            final HashFunction hashFunction = input -%3E %7B//parenthesis%0A                final MessageDigest sha12 = MessageDigest.getInstance(%22SHA12%22
+interface Op %7B%0A            long calculate(final long first, final long second
 );%0A 
@@ -3069,32 +3069,35 @@
 d);%0A        
+%7D%0A%0A
         
 return sha12
@@ -3088,139 +3088,100 @@
     
-return sha12.digest(input.getBytes());//return statement%0A            %7D;%0A            final byte%5B%5D bytes = hashFunction.hash(%22hello%22)
+void demo() throws Exception %7B%0A            final Op addition = (left, right) -%3E left + right
 ;%0A  

Add example for functional interfaces with multiple parameters.