package CognitiveModel.ModelFiles.XPCdependencies;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Parser class that parses the UDP discovery BECN packet. The format of the packet is
 * - 4 bytes: BECN
 * - 1 byte: 0
 * - 2 bytes: XPlaneConnect server port e.g. '49009'
 * - 4 bytes: X-Plane version e.g. '11260'
 * - null terminated string: XPlaneConnect plugin version e.g. '1.3-rc.1'
 */
public class BeaconParser {

    private static String BECN = "BECN";

    private static int XPC_PORT_OFFSET = BECN.length() + 1;
    private static int XPC_PORT_LEN = 2;
    private static int XPC_VERSION_OFFSET = XPC_PORT_OFFSET + XPC_PORT_LEN;
    private static int XPC_VERSION_LEN = 4;
    private static int XPC_PLUGIN_VERSION_OFFSET = XPC_VERSION_OFFSET + XPC_VERSION_LEN;


    public Beacon readBCN(DatagramPacket packet) throws IOException {
        if (packet.getLength() < BECN.length()) {
            throw new IOException("BECN response too short");
        }

        byte[] data = packet.getData();

        String command = new String(data, 0, BECN.length());
        if (!command.equals(BECN)) {
            throw new IOException("Expected " + BECN + " got '" + command + "'");
        }

        InetAddress address = packet.getAddress();
        ByteBuffer bb = ByteBuffer.wrap(data);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        // 2 bytes: port as short + converted to an int
        int port = bb.getShort(XPC_PORT_OFFSET) & 0xffff;

        // 4 bytes: x plane version as int
        int version = bb.getInt(XPC_VERSION_OFFSET);

        // plugin version
        String pluginVersion = new String(data, XPC_PLUGIN_VERSION_OFFSET, packet.getLength() - XPC_PLUGIN_VERSION_OFFSET);

        return new Beacon(address, port, pluginVersion.trim(), version);
    }
}