package ru.redguy;

import org.reflections.Reflections;
import org.reflections.scanners.*;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;

public class INF {

    static HashMap<String, Task> tasks = new HashMap<>();

    public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ExecutionException, InterruptedException {
        FilterBuilder fb = new FilterBuilder();
        fb.includePackage("ru.redguy.tasks");

        ConfigurationBuilder configBuilder =
                new ConfigurationBuilder()
                        .filterInputsBy(fb)
                        .setScanners(
                                new TypeAnnotationsScanner(),
                                new MethodParameterScanner(),
                                new MethodAnnotationsScanner(),
                                new FieldAnnotationsScanner(),
                                new SubTypesScanner()
                        );

        configBuilder.addUrls(ClasspathHelper.forPackage("ru.redguy.tasks"));
        Reflections reflections = new Reflections(configBuilder);

        for (Class<?> mClass : reflections.getTypesAnnotatedWith(ATask.class, false)) {
            ATask annotation = mClass.getAnnotation(ATask.class);
            tasks.put(annotation.value(),(Task) mClass.getConstructor().newInstance());
        }

        Scanner scanner = new Scanner(System.in);
        String inp;
        while(true) {
            inp = scanner.nextLine();
            switch (inp) {
                case "exit": System.exit(0); break;
                case "list": tasks.forEach((i,b) -> System.out.println(i)); break;
                default: tasks.getOrDefault(inp, new Task() {@Override public void run(){}}).run(); break;
            }
        }
    }
}
