package ex8;

import ch.usi.dag.disl.annotation.After;
import ch.usi.dag.disl.annotation.Before;
import ch.usi.dag.disl.annotation.ThreadLocal;
import ch.usi.dag.disl.dynamiccontext.DynamicContext;
import ch.usi.dag.disl.marker.BodyMarker;
import ch.usi.dag.disl.marker.BytecodeMarker;
import ch.usi.dag.disl.staticcontext.InstructionStaticContext;
import org.objectweb.asm.Opcodes;

public class Instrumentation {

    @ThreadLocal
    private static long staticCount;

    @ThreadLocal
    private static long dynamicCount;

    @ThreadLocal
    private static long specialCount;

    @ThreadLocal
    private static long virtualCount;

    @Before(marker = BytecodeMarker.class,
            args = "invokestatic, invokespecial, invokevirtual, invokedynamic")
    static void handleInvoke(final InstructionStaticContext isc) {
        switch (isc.getOpcode()) {
            case Opcodes.INVOKESTATIC -> staticCount++;
            case Opcodes.INVOKEDYNAMIC -> dynamicCount++;
            case Opcodes.INVOKESPECIAL -> specialCount++;
            case Opcodes.INVOKEVIRTUAL -> virtualCount++;
        }
    }

    @After(marker = BodyMarker.class, scope = "void run()", guard = IsNonStaticGuard.class)
    static void endThread(final DynamicContext dc) {
        if (dc.getThis() instanceof Thread) {
            System.out.printf("Thread: %20s - static: %6d - special: %6d - virtual: %6d - dynamic: %6d\n",
                    ((Thread) dc.getThis()).getName(),
                    staticCount,
                    specialCount,
                    virtualCount,
                    dynamicCount);
        }
    }
}
