package dst.ass2.aop.management;

import dst.ass2.aop.IPluginExecutable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

import java.util.Timer;
import java.util.TimerTask;

@Aspect
public class ManagementAspect {
    @Around("execution(* dst.ass2.aop.IPluginExecutable.execute(..)) && @annotation(Timeout)")
    public Object around(ProceedingJoinPoint point) {
        // setup interruptionTimer.
        Timeout timeoutAnn = ((MethodSignature) point.getSignature()).getMethod().getAnnotation(Timeout.class);
        System.out.println("ManagementAspect - sched");

        Timer interruptionTimer = new Timer(true);
        interruptionTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("ManagementAspect - interrupt");
                ((IPluginExecutable) point.getTarget()).interrupted();
            }
        }, timeoutAnn.value());

        //execute actual function
        Object result = null;
        try {
            result = point.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        // once the function completed, cancel interruptionTimer and return results.
        interruptionTimer.cancel();
        return result;
    }
}
