package tech.nevets.tvpn.wg;

public class WGConf {
    public Interface iface;
    public Peer peer;
    public AllowedIP allowedIP;

    public WGConf(Interface iface, Peer peer, AllowedIP allowedIP) {
        this.iface = iface;
        this.peer = peer;
        this.allowedIP = allowedIP;
    }

    /*
    struct WIREGUARD_INTERFACE {
        WIREGUARD_INTERFACE_FLAG Flags;        < Bitwise combination of flags
        WORD ListenPort;                       < Port for UDP listen socket, or 0 to choose randomly
        BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; < Private key of interface
        BYTE PublicKey[WIREGUARD_KEY_LENGTH];  < Corresponding public key of private key
        DWORD PeersCount;                      < Number of peer structs following this struct
    };

    typedef enum {
        WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0),  < The PublicKey field is set
        WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), < The PrivateKey field is set
        WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), < The ListenPort field is set
        WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3)    < Remove all peers before adding new ones
    } WIREGUARD_INTERFACE_FLAG;
    */
    public class Interface {
        public int flags;
        public int port; // Should be 0 for random
        public byte[] privateKey;
        public byte[] publicKey; // Should be unused, will be calculated by privateKey
        public int peersCount; // Should be 1
    }

    /*
    struct WIREGUARD_PEER {
        WIREGUARD_PEER_FLAG Flags;               < Bitwise combination of flags
        DWORD Reserved;                          < Reserved; must be zero
        BYTE PublicKey[32];    < Public key, the peer's primary identifier
        BYTE PresharedKey[32]; < Preshared key for additional layer of post-quantum resistance
        WORD PersistentKeepalive;                < Seconds interval, or 0 to disable
        SOCKADDR_INET Endpoint;                  < Endpoint, with IP address and UDP port number
        DWORD64 TxBytes;                         < Number of bytes transmitted
        DWORD64 RxBytes;                         < Number of bytes received
        DWORD64 LastHandshake;                   < Time of the last handshake, in 100ns intervals since 1601-01-01 UTC
        DWORD AllowedIPsCount;                   < Number of allowed IP structs following this struct
    };

    typedef enum {
        WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0,           < The PublicKey field is set
        WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1,        < The PresharedKey field is set
        WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, < The PersistentKeepAlive field is set
        WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3,             < The Endpoint field is set
        WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5,      < Remove all allowed IPs before adding new ones
        WIREGUARD_PEER_REMOVE = 1 << 6,                   < Remove specified peer
        WIREGUARD_PEER_UPDATE = 1 << 7                    < Do not add a new peer
    } WIREGUARD_PEER_FLAG;
    */
    public class Peer {
        public int flags;
        public int reserved = 0; // "Must be 0"
        public byte[] publicKey;
        public byte[] presharedKey;
        public int persistentKeepalive; // In seconds, or 0 to disable
        public byte[] endpoint; // Going to have to figure out how to parse this. IP + UDP Port
        public int txBytes; // Unused, changed later
        public int rxBytes; // Unused, changed later
        public long lastHandshake; // Time of last handshake, in 100ns intervals since 1601-01-01 UTC. Unused, changed later
        public int allowedIPsCount; // Number of allowed IP structures
    }

    /*
    struct WIREGUARD_ALLOWED_IP {
        union
        {
            IN_ADDR V4;
            IN6_ADDR V6;
        } Address;                    < IP address
        ADDRESS_FAMILY AddressFamily; < Address family, either AF_INET or AF_INET6
        BYTE Cidr;                    < CIDR of allowed IPs
    };
    */
    public class AllowedIP {
        public String address; // IP address; the V4 member is an IN_ADDR and the V6 member is an IN6_ADDR
        public String addressFamily; // Address family, either AF_INET or AF_INET6
        public byte cidr; // The CIDR of the address range
    }
}

