package net.ranides.demo.debugger;

import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.request.BreakpointRequest;
import net.ranides.demo.debugger.util.SimpleDebugger;

import java.util.Optional;

public class AppDebugger {

    private static final String EXAMPLE = "net.ranides.demo.debugger.AppObservable$ExampleObject@19";

    public static void main(String[] args) {

        try (var debugger = new SimpleDebugger()) {
            var example = debugger.connect("localhost", "5151").locate(EXAMPLE);

            System.out.println(" - debug session...");

            // EXAMPLE: short syntax: method call at "location"
            var valueE = (Double) example.call("methodNum", new Object[]{"3", "7", 3.0});
            System.out.printf(" - methodNum = '%s'%n", valueE);


            // EXAMPLE: short syntax: variable access at "location"
            var valueF = (Integer) example.variable("counter");
            System.out.printf(" - counter = '%s'%n", valueF);


            // EXAMPLE: short syntax: invoke method inside remote context
            var valueA = example.eval(context -> {
                var counter = (Integer) context.variable("counter");
                return (Integer) context.call("methodInt", new Object[]{6, counter});
            });
            System.out.printf(" - methodInt = '%s'%n", valueA);


            // EXAMPLE: manually create breakpoint & process debug events
            BreakpointRequest breakpoint = debugger.breakpoint(example);
            int[] result = {0};
            int[] repeat = {0};

            debugger.loop(context -> {
                if (!context.matches(example)) {
                    System.out.printf(" * ignore event: %s%n", context.event());
                    return Optional.empty();
                }

                Integer counter = (Integer) context.variable("counter");
                System.out.printf(" * counter = %d%n", counter);

                result[0] += counter;

                if (repeat[0]++ > 10) {
                    breakpoint.setEnabled(false);
                    context.stop();
                    return Optional.of("calculated");
                }
                return Optional.empty();
            });
            System.out.printf(" - result = %d%n", result[0]);

        } catch (VMDisconnectedException e) {
            System.out.println("Virtual Machine is disconnected.");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("Disconnected.");
        }
    }
}
