package cs451.net.handler;

import cs451.net.event.NetEvent;
import cs451.net.event.NetEventType;
import cs451.parser.Host;
import cs451.parser.Parser;
import cs451.tools.Logger;

/**
 * NetEventHandler Interface
 *
 * @author C. Hölzl
 */
public interface NetEventHandlerInterface {


    /**
     * Sends Messages on condition (500ms event timer)
     */
    default void broadcastIf(){}
    /**
     * Delivers Messages on condition (500ms event timer)
     */
    default void deliverIf(){}

    /**
     * Hearth-beat (1s event timer)
     */
    default void beat(){}


    /**
     * Delivers a NetEvent to the next layer synchronously
     * @param ne NetEvent
     */
    void deliverNextSync(NetEvent ne);
    /**
     * Sends a NetEvent to the next layer synchronously
     * @param ne NetEvent
     */
    void broadcastNextSync(NetEvent ne);
    /**
     * Crashes a NetEvent to the next layer synchronously
     * @param ne NetEvent
     */
    void crashNextSync(NetEvent ne);
    /**
     * Recovers a NetEvent to the next layer synchronously
     * @param ne NetEvent
     */
    void recoverNextSync(NetEvent ne);

    /**
     * Delivers a NetEvent to the next layer asynchronously
     * @param ne NetEvent
     */
    void deliverNextAsync(NetEvent ne);
    /**
     * Sends a NetEvent to the next layer asynchronously
     * @param ne NetEvent
     */
    void broadcastNextAsync(NetEvent ne);
    /**
     * Crashes a NetEvent to the next layer asynchronously
     * @param ne NetEvent
     */
    void crashNextAsync(NetEvent ne);
    /**
     * Recovers a NetEvent to the next layer asynchronously
     * @param ne NetEvent
     */
    void recoverNextAsync(NetEvent ne);

    /**
     * Handles a NetEvent
     * @param et EventType
     * @param ne NetEvent
     */
    default void onEvent(NetEventType et, NetEvent ne){
        switch (et){
            case DLVR: deliver(ne);
                break;
            case BCST: broadcast(ne);
                break;
            case CRSH: crash(ne);
                break;
            case RCVR: recover(ne);
                break;
            default:
                Logger.error("Unhandled EventType:"+et);
        }
    }


    /**
     * Send Event Handler
     * @param ne NetEvent
     */
    default void broadcast(NetEvent ne){
        broadcastNextSync(ne);
    }
    /**
     * Deliver Event Handler
     * @param ne NetEvent
     */
    default void deliver(NetEvent ne){
        deliverNextSync(ne);
    }
    /**
     * Crash Event Handler
     * @param ne NetEvent
     */
    default void crash(NetEvent ne){
        crashNextSync(ne);
    }
    /**
     * Recover Event Handler
     * @param ne NetEvent
     */
    default void recover(NetEvent ne){
        recoverNextSync(ne);
    }

    /**
     * Starts the NetEventHandler
     * @param h host (self)
     * @param p parser
     */
    void start(Host h, Parser p);

    /**
     * Stops the NetEventHandler
     */
    void stop();

    /**
     * Checks if NetEventHandler is Finished
     * @return if it is done with its work
     */
    default boolean isDone(){ return true;}
}
