package tc.oc.commons.bukkit.suspend;

import java.util.Set;
import javax.inject.Inject;

import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.commons.core.util.ThrowingConsumer;
import tc.oc.minecraft.suspend.Suspendable;

import static com.google.common.base.Preconditions.checkState;

/**
 * Listens for {@link ServerSuspendEvent} and dispatches it to all {@link Suspendable}s
 */
public class SuspendListener implements PluginFacet, Listener {

    private final ThrowingConsumer<ServerSuspendEvent, EventException> yielder;

    @Inject SuspendListener(Set<Suspendable> suspendables) {
        ThrowingConsumer<ServerSuspendEvent, EventException> yielder = Event::yield;
        for(Suspendable suspendable : suspendables) {
            ThrowingConsumer<ServerSuspendEvent, EventException> next = yielder;
            yielder = event -> suspendable.suspend(() -> next.acceptThrows(event));
        }
        this.yielder = yielder;
    }

    @EventHandler
    void onSuspend(ServerSuspendEvent event) throws EventException {
        yielder.acceptThrows(event);
        checkState(!event.canYield(), "Suspendable didn't yield");
    }
}
