import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.List;

/**
 * @author Anastasiya Solodkaya.
 */
public class CountedLoopProposal9 {
    public static void main(String[] args) {
        MethodHandle methodHandle0 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class));
        System.out.println("methodHandle0.type() = " + methodHandle0.type());
        MethodHandle methodHandle1 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class));
        System.out.println("methodHandle1.type() = " + methodHandle1.type());
        MethodHandle methodHandle2 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class, List.class));
        System.out.println("methodHandle2.type() = " + methodHandle2.type());

        MethodHandle methodHandle3 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, String.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class));
        System.out.println("methodHandle3.type() = " + methodHandle3.type());
        MethodHandle methodHandle4 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, String.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class, String.class));
        System.out.println("methodHandle4.type() = " + methodHandle4.type());
        MethodHandle methodHandle5 = MethodHandles.countedLoop(
                MethodSet.iteration(int.class, String.class, List.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class, String.class, List.class));
        System.out.println("methodHandle5.type() = " + methodHandle5.type());
    }

    static class MethodSet {
        static int iterationInt(List<String> loopParams) {
            return 0;
        }

        static int iterationInt(String loopParam0, List<String> loopParams1) {
            return 0;
        }

        static String bodyString(int counter) {
            return "";
        }

        static String bodyString(int counter, String localParam) {
            return "";
        }

        static String bodyString(int counter, String localParam, String loopParam0) {
            return "";
        }

        static String bodyString(int counter, String localParam, String loopParam0, List<String> loopParam1) {
            return "";
        }

        static String bodyString(int counter, String localParam, List<String> loopParams) {
            return "";
        }

        static String initString() {
            return "";
        }

        static MethodHandle body(Class returnType, Class... params) {
            return findStatic("body", returnType, params);
        }

        static MethodHandle init(Class returnType, Class... params) {
            return findStatic("init", returnType, params);
        }

        static MethodHandle iteration(Class returnType, Class... params) {
            return findStatic("iteration", returnType, params);
        }

        private static MethodHandle findStatic(String prefix, Class returnType, Class[] params) {
            try {
                String simpleName = returnType.getSimpleName();
                simpleName = simpleName.substring(0, 1).toUpperCase() + simpleName.substring(1);
                return MethodHandles.lookup().findStatic(MethodSet.class, prefix + simpleName, MethodType.methodType(returnType, params));
            } catch (NoSuchMethodException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
        }


    }

}
