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

/**
 * @author Anastasiya Solodkaya.
 */
public class CountedLoopProposal11 {
    private  static int counter = 0;
    public static void main(String[] args) {
        // ----------------- ALL NON-NULL
        // iterations
        runSimple(
                MethodSet.iteration(int.class, int.class, List.class),
                MethodSet.init(String.class, int.class),
                MethodSet.body(String.class, int.class)
        );
        // ok - init
        runSimple(
                MethodSet.iteration(int.class),
                MethodSet.init(String.class, int.class, List.class),
                MethodSet.body(String.class, int.class)
        );
        // failed - iterations contradicts init
        runSimple(
                MethodSet.iteration(int.class, List.class),
                MethodSet.init(String.class, int.class),
                MethodSet.body(String.class, int.class, String.class)
        );
        // failed: body contradicts iteration and init
        runSimple(
                MethodSet.iteration(int.class),
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class, List.class)
        );

        // ----------------- INIT = NULL
        // ok: iterations defines parameter list
        runSimple(
                MethodSet.iteration(int.class, List.class),
                null,
                MethodSet.body(String.class, int.class, String.class)
        );

        // failed: body contradicts iterations
        runSimple(
                MethodSet.iteration(int.class, int.class, List.class),
                null,
                MethodSet.body(String.class, int.class, String.class, int.class, List.class, int.class)
        );
        // failed: body contradicts iterations
        runSimple(
                MethodSet.iteration(int.class),
                null,
                MethodSet.body(void.class, int.class, int.class, List.class)
        );

            // ----------------- ITERATIONS = NULL, INIT IS NOT NULL
        runSimple(
                null,
                MethodSet.init(String.class),
                MethodSet.body(String.class, int.class, String.class)
        );
        runSimple(
                null,
                MethodSet.init(String.class, int.class),
                MethodSet.body(String.class, int.class, String.class, int.class)
        );
        runSimple(
                null,
                MethodSet.init(String.class, int.class),
                MethodSet.body(String.class, int.class, String.class)
        );
        runSimple(
                null,
                MethodSet.init(String.class, int.class),
                MethodSet.body(String.class, int.class)
        );
        runSimple(
                null,
                MethodSet.init(String.class, int.class, int.class),
                MethodSet.body(String.class, int.class, String.class, int.class)
        );
        runSimple(
                null,
                MethodSet.init(void.class),
                MethodSet.body(void.class, int.class, int.class)
        );
//        runSimple(
//                null,
//                null,
//                null
//        );
        // ----------------- ITERATIONS = NULL, INIT = NULL
        // body: defines parameter list
        runSimple(
                null,
                null,
                MethodSet.body(void.class, int.class, int.class)
        );


    }

    private static void runSimple(MethodHandle iteration, MethodHandle init, MethodHandle body) {
        try {
            System.out.printf("%d -------------------------------%n", counter);
            System.out.printf("iteration=%s, init=%s, body=%s%n",
                    (iteration == null ? null : iteration.type()),
                    (init == null ? null : init.type()),
                    (body == null ? null : body.type()));
            MethodHandle methodHandle0 = MethodHandles.countedLoop(
                    iteration,
                    init,
                    body);
            System.out.println("methodHandle.type() = " + methodHandle0.type());
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
        counter++;
    }


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

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

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

        static int iterationInt(int loopParam0, List<String> loopParams1, int u) {
            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 bodyString(int counter, String h, int y, List<String> loopParams, int o) {
            return "";
        }
        static String bodyString(int counter, String h, int y) {
            return "";
        }

        static String bodyString(int counter, String h, int y, List<String> loopParams) {
            return "";
        }
        static void bodyVoid(int counter, int y, List<String> loopParams) {
        }
        static void bodyVoid(int counter, int y) {
        }

        static void bodyVoid(int counter) {
        }

        static String initString() {
            return "";
        }
        static String initString(int i) {
            return "";
        }
        static String initString(int i, int y) {
            return "";
        }

        static String initString(int i, List<String> p1) {
            return "";
        }
        static String initString(List<String> p1) {
            return "";
        }
        static void initVoid() {
        }

        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;
            }
        }


    }

}
