package cs451.net.handler;

import cs451.net.NetManager;
import cs451.net.event.NetEvent;
import cs451.parser.Host;
import cs451.parser.Parser;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * NetEventHandler abstraction class
 *
 * @author C. Hölzl
 */
public abstract class NetEventHandlerAbstract implements NetEventHandlerInterface {


    /**
     * Deliver & Broadcast Layers to handle resulting operation
     */
    private final Class<? extends NetEventHandlerAbstract> deliverLayer;
    private final Class<? extends NetEventHandlerAbstract> broadcastLayer;

    public final AtomicBoolean active = new AtomicBoolean(true);


    /**
     * Initialized the main NetEventHandler fields
     * @param deliverLayer layer in which NetEvents should be delivered
     * @param broadcastLayer layer in which NetEvents should be broadcast
     */
    NetEventHandlerAbstract(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
        this.deliverLayer = deliverLayer;
        this.broadcastLayer = broadcastLayer;
    }


    /**
     * Delivers a NetEvent Synchronously
     * @param ne NetEvent
     */
    public void deliverNextSync(NetEvent ne){
        NetManager.deliverSync(deliverLayer,ne);
    }
    /**
     * Sends a NetEvent Synchronously
     * @param ne NetEvent
     */
    public void sendNextSync(NetEvent ne){
        NetManager.sendSync(broadcastLayer,ne);
    }
    /**
     * Crashes a NetEvent Synchronously
     * @param ne NetEvent
     */
    public void crashNextSync(NetEvent ne){
        NetManager.crashSync(deliverLayer,ne);
    }

    /**
     * Delivers a NetEvent Asynchronously
     * @param ne NetEvent
     */
    public void deliverNextAsync(NetEvent ne){
        NetManager.deliver(deliverLayer,ne);
    }
    /**
     * Sends a NetEvent Asynchronously
     * @param ne NetEvent
     */
    public void sendNextAsync(NetEvent ne){
        NetManager.send(broadcastLayer,ne);
    }
    /**
     * Crashes a NetEvent Asynchronously
     * @param ne NetEvent
     */
    public void crashNextAsync(NetEvent ne) {
        NetManager.crash(deliverLayer,ne);
    }

    /**
     * Starts the NetEventHandler
     * @param h host (self)
     * @param p parser
     */
    public void start(Host h, Parser p) {
        Objects.requireNonNull(h);
        Objects.requireNonNull(p);
        active.set(true);
    }

    /**
     * Stops the NetEventHandler
     */
    public void stop() {
        active.set(false);
    }

}
