package SimkitOpenDis7Examples;

import OpenDis7Examples.ChannelOpenDis7;
import edu.nps.moves.dis7.enumerations.VariableRecordType;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;

/**
 * One of the simplest non-trivial Event Graph models. A series of Arrival
 * events is scheduled based on an inter arrival time random variate. The state
 * variable, simply counts the number of these arrivals.
 *
 * @author ahbuss
 * @author brutzman
 */
public class ArrivalProcessOpenDis7 extends SimEntityBase {
    
    private final ChannelOpenDis7 channelOpenDis7 = new ChannelOpenDis7();

    /**
     * Generates interarrival times
     */
    private RandomVariate interarrivalTimeGenerator;

    /**
     * State variable that counts the number of Arrival events
     */
    protected int numberArrivals;
    
    /** Initialize channel setup for OpenDis7 and report a test PDU */
    private void initializeChannelOpenDis7()
    {
        channelOpenDis7.setUpNetworkInterface();
        channelOpenDis7.printlnTRACE ("opendis7.getNetworkAddress()=" + channelOpenDis7.getNetworkAddress() +
                                             ", getNetworkPort()="    + channelOpenDis7.getNetworkPort());
        
        channelOpenDis7.sendCommentPdu(VariableRecordType.OTHER, "ArrivalProcessOpenDis7 initialized");
    }

    /**
     * Instantiate an ArrivalProcess with the given interarrivalTimeGenerator
     *
     * @param interarrivalTimeGenerator Given RandomVariate for interarrival
     * times
     */
    public ArrivalProcessOpenDis7(RandomVariate interarrivalTimeGenerator) {
        this.interarrivalTimeGenerator = interarrivalTimeGenerator;
        initializeChannelOpenDis7();
    }

    /**
     * If the ArrivalProcess is instantiated using the zero-argument
     * constructor, be sure the set the interarrivalTimeGenerator with an
     * explicit call to its setter method.
     */
    public ArrivalProcessOpenDis7() {
        initializeChannelOpenDis7();
    }

    /**
     * Initialize numberArrivals to 0
     */
    @Override
    public void reset() {
        super.reset();
        numberArrivals = 0;
    }

    /**
     * Schedule the first Arrival event with delay generated by
     * interarrivalTimeGenerator
     */
    public void doRun() {
        firePropertyChange("numberArrivals", getNumberArrivals());
        
        // TODO send simulation management PDUs via DIS channel, announce commencement

        waitDelay("Arrival", interarrivalTimeGenerator);
    }

    /**
     * Increment numberArrivals<br>
     * Schedule next Arrival event with delay generated by
     * interarrivalTimeGenerator
     */
    public void doArrival() {
        int oldNumberArrivals = getNumberArrivals();
        numberArrivals += 1;
        firePropertyChange("numberArrivals", oldNumberArrivals, getNumberArrivals());
        
        // TODO announce selected arrivals via DIS channel

        waitDelay("Arrival", interarrivalTimeGenerator);
    }

    /**
     * @return the interarrivalTimeGenerator
     */
    public RandomVariate getInterarrivalTimeGenerator() {
        return interarrivalTimeGenerator;
    }

    /**
     * @param interarrivalTimeGenerator the interarrivalTimeGenerator to set
     */
    public void setInterarrivalTimeGenerator(RandomVariate interarrivalTimeGenerator) {
        this.interarrivalTimeGenerator = interarrivalTimeGenerator;
    }

    /**
     * @return the numberArrivals
     */
    public int getNumberArrivals() {
        return numberArrivals;
    }

    /**
     * @return the channelOpenDis7
     */
    public ChannelOpenDis7 getChannelOpenDis7() {
        return channelOpenDis7;
    }
}