package com.example.futures;
import com.tccc.kos.commons.util.KosUtil;
import com.tccc.kos.commons.util.concurrent.future.FutureEvent;
import com.tccc.kos.commons.util.concurrent.future.FutureWork;
import com.tccc.kos.commons.util.misc.Str;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FutureExamples1 {
    public static final int DURATION = 2000;
    public static final int EXTRA = 200;
    public static final int TIMEOUT = DURATION + EXTRA;
    public void run() {
        log.info("> FutureExamples1.run()");
        runWithAllFourEndStates();
    }
    /**
     * Runs four tasks, demonstrating the different end states and event calls.
     */
    private void runWithAllFourEndStates() {
        FutureWork future1 = createFuture("fw-1"); (1)
        future1.run();
        future1.waitUntilFinished(TIMEOUT);
        FutureWork future2 = createFuture("fw-2"); (2)
        future2.setTimeout(1000, f -> f.fail("Something went wrong"));
        future2.run();
        future2.waitUntilFinished(TIMEOUT);
        FutureWork future3 = createFuture("fw-3"); (3)
        future3.run();
        KosUtil.sleep(1000);
        future3.cancel("The user changed his/her mind");
        future3.waitUntilFinished(TIMEOUT);
        FutureWork future4 = createFuture("fw-4"); (4)
        future4.run();
        KosUtil.sleep(1000);
        future4.abort("An internal operation unexpectedly failed");
        future4.waitUntilFinished(TIMEOUT);
    }
    protected static FutureWork createFuture(String name) { (5)
        FutureWork future = new FutureWork(name, f -> {
            KosUtil.scheduleCallback(f::success, DURATION);
        }, DURATION);
        appendAllEvents(future);
        return future;
    }
    protected static void appendAllEvents(FutureWork future) {
        //@formatter:off
        future.append("started",     FutureEvent.START,     f -> logIt(f, "STARTED"    ));
        future.append("successful",  FutureEvent.SUCCESS,   f -> logIt(f, "SUCCESSFUL" ));
        future.append("failed",      FutureEvent.FAIL,      f -> logIt(f, "FAILED"     ));
        future.append("cancelled",   FutureEvent.CANCEL,    f -> logIt(f, "CANCELLED"  ));
        future.append("aborted",     FutureEvent.ABORT,     f -> logIt(f, "ABORTED"    ));
        future.append("done",        FutureEvent.DONE,      f -> logIt(f, "DONE"       ));
        future.append("terminated",  FutureEvent.TERMINATE, f -> logIt(f, "TERMINATED" ));
        future.append("complete",    FutureEvent.COMPLETE,  f -> logIt(f, "COMPLETED"  ));
        future.append("finished",    FutureEvent.FINISHED,  f -> logIt(f, "FINISHED"   ));
        future.append("interrupted", FutureEvent.INTERRUPT, f -> logIt(f, "INTERRUPTED"));
        //@formatter:on
    }
    protected static void logIt(FutureWork future, String eventName) {
        log.info(String.format("> %s: %-10s: %s",
                future.getName(), eventName, Str.notNull(future.getReason())));
    }
}