/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package OpenDis7Examples;

import edu.nps.moves.dis7.pdus.Pdu;
import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface;
import edu.nps.moves.dis7.utilities.DisTime;
import edu.nps.moves.dis7.utilities.stream.PduRecorder;
import java.net.InetAddress;
import java.net.UnknownHostException;
// import jdk.internal.vm.annotation.IntrinsicCandidate;

/**
 *
 * @author brutzman
 */
public class ChannelOpenDis7 {
    /**
     * Output prefix to help with logging by identifying this class.
     */
    private static       String TRACE_PREFIX = "[OpenDis7]";
            static       String thisHostName = "localhost";
    private static final String NETWORK_ADDRESS_DEFAULT = "239.1.2.3";
    private static final int       NETWORK_PORT_DEFAULT = 3000;
    private static final String  DEFAULT_PDULOG_OUTPUT_DIRECTORY = "./pduLog";
    
    protected boolean verboseComments = true;
    String networkAddress = NETWORK_ADDRESS_DEFAULT;
    int       networkPort = NETWORK_PORT_DEFAULT;
    DisTime.TimestampStyle timestampStyle = DisTime.TimestampStyle.IEEE_ABSOLUTE;
    
    // class variables
    DisThreadedNetworkInterface             disNetworkInterface;
    DisThreadedNetworkInterface.PduListener pduListener;
    Pdu                                     receivedPdu;
    PduRecorder                             pduRecorder;

    public ChannelOpenDis7()
    {
        DisTime.setTimestampStyle(timestampStyle); // DISTime is a singleton shared class
        
        try
        {
            thisHostName = InetAddress.getLocalHost().getHostName();
            System.out.println(TRACE_PREFIX + "thisHostName=" + thisHostName);
        }
        catch (UnknownHostException uhe)
        {
            System.out.println(TRACE_PREFIX + thisHostName + "not connected to network: " + uhe.getMessage());
        }
    }
    
    /**
     * get current networkAddress as a string
     * @return the networkAddress
     */
    public String getNetworkAddress() {
        return networkAddress;
    }

    /**
     * set current networkAddress using a string
     * @param newNetworkAddress the networkAddress to set
     */
    public final void setNetworkAddress(String newNetworkAddress) {
        this.networkAddress = newNetworkAddress;
    }

    /**
     * get current networkPort
     * @return the networkPort
     */
    public int getNetworkPort() {
        return networkPort;
    }

    /**
     * set current networkPort
     * @param newNetworkPort the networkPort to set
     */
    public final void setNetworkPort(int newNetworkPort) {
        this.networkPort = newNetworkPort;
    }

    /**
     * Get timestampStyle used by PduFactory
     * @return current timestampStyle
     */
    public DisTime.TimestampStyle getTimestampStyle() {
        return timestampStyle;
    }

    /**
     * Set timestampStyle used by PduFactory
     * @param newTimestampStyle the timestampStyle to set
     */
    public void setTimestampStyle(DisTime.TimestampStyle newTimestampStyle) {
        timestampStyle = newTimestampStyle;
        DisTime.setTimestampStyle(newTimestampStyle);
    }

    /**
     * Initialize network interface, choosing best available network interface
     */
    public void setUpNetworkInterface() {
        disNetworkInterface = new DisThreadedNetworkInterface(getNetworkAddress(), getNetworkPort());
        disNetworkInterface.setDescriptor("ExampleSimulationProgram pdu looping");
        System.out.println("Network confirmation:" + " address=" + disNetworkInterface.getAddress() + //  disNetworkInterface.getMulticastGroup() +
        " port=" + disNetworkInterface.getPort()); // + disNetworkInterface.getDisPort());
        pduListener = new DisThreadedNetworkInterface.PduListener() {
            /** Callback handler for listener */
            @Override
            public void incomingPdu(Pdu newPdu) {
                receivedPdu = newPdu;
            }
        };
        disNetworkInterface.addListener(pduListener);
        String pduLogOutputDirectory = DEFAULT_PDULOG_OUTPUT_DIRECTORY;
        System.out.println("Beginning pdu save to directory " + pduLogOutputDirectory);
        pduRecorder = new PduRecorder(pduLogOutputDirectory, getNetworkAddress(), getNetworkPort()); // assumes save
        pduRecorder.setEncodingPduLog(PduRecorder.ENCODING_PLAINTEXT);
        pduRecorder.setVerbose(true); // either sending, receiving or both
        pduRecorder.start(); // begin running
    }

    /** All done, release network resources */
    public void tearDownNetworkInterface() {
        pduRecorder.stop(); // handles disNetworkInterface.close(), tears down threads and sockets
    }

    /** 
     * Send a single Protocol Data Unit (PDU) of any type
     * @param pdu the pdu to send
     */
    protected void sendSinglePdu(Pdu pdu)
    {
        try
        {
            disNetworkInterface.send(pdu);
            Thread.sleep(100); // TODO consider refactoring the wait logic and moving externally
        } 
        catch (InterruptedException ex)
        {
            System.err.println(this.getClass().getName() + " Error sending PDU: " + ex.getLocalizedMessage());
            System.exit(1);
        }
    }

    /**
     * test for verboseComments mode
     * @return whether verboseComments mode is enabled
     */
    public boolean isVerboseComments() {
        return verboseComments;
    }

    /**
     * set verboseComments mode
     * @param newVerboseComments whether verboseComments mode is enabled
     */
    public void setVerboseComments(boolean newVerboseComments) {
        this.verboseComments = newVerboseComments;
    }

    /**
     * @return the TRACE_PREFIX
     */
    public static String getTRACE_PREFIX() {
        return TRACE_PREFIX;
    }

    /**
     * @param aTRACE_PREFIX the TRACE_PREFIX to set
     */
    public static void setTRACE_PREFIX(String aTRACE_PREFIX) {
        TRACE_PREFIX = aTRACE_PREFIX;
    }

    /**
     * Print message with TRACE_PREFIX prepended
     * @param message String to print
     */
    public void printTRACE(String message) {
        System.out.print(TRACE_PREFIX + message);
    }
    /**
     * Print message with TRACE_PREFIX prepended
     * @param message String to print
     */
    public void printlnTRACE(String message) {
        System.out.println(TRACE_PREFIX + message);
    }
}