package ex10;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class Profiler {
    private static final ConcurrentMap<String, Set<String>> methodInvocations = new ConcurrentHashMap<>();

    private static final Map<String, Set<String>> methodDeclarations = new HashMap<>();

    private static final Map<String, Set<String>> inheritedMethods = new HashMap<>();

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            for (final String className : methodInvocations.keySet()) {
                System.out.println("=== Class Name: " + className + " ===");
                for (final String method : methodDeclarations.getOrDefault(className, Set.of())) {
                    System.out.println("Declared: " + method);
                }
                for (final String method : inheritedMethods.getOrDefault(className, Set.of())) {
                    System.out.println("Inherited: " + method);
                }
                for (final String method : methodInvocations.get(className)) {
                    System.out.println("Executed: " + className.replace('.', '/') + "." + method);
                }
            }
        }));
    }


    private Profiler() {
    }

    private static void register(final String className, final String methodName, final Map<String, Set<String>> methods) {
        methods.computeIfAbsent(className, ignored -> Collections.synchronizedSet(new HashSet<>()))
                .add(methodName);
    }

    public static void registerInvoke(final String className, final String methodName) {
        register(className, methodName, methodInvocations);
    }

    public static void registerDeclared(final String className, final String methodName) {
        register(className, methodName, methodDeclarations);
    }

    public static void registerInherited(final String className, final String methodName) {
        register(className, methodName, inheritedMethods);
    }
}
