using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Pilz.Net;

public static class NetworkFeatures
{
    public static IPAddress? GetIPFromHost(string hostName)
    {
        return Dns.GetHostAddresses(hostName).FirstOrDefault(n => n.AddressFamily == AddressFamily.InterNetwork);
    }

    public static object? GetHostFromIP(string ip)
    {
        return Dns.GetHostEntry(ip)?.HostName;
    }

    public static UnicastIPAddressInformation? GetLocalIPInformations()
    {
        UnicastIPAddressInformation? addr = null;

        foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (addr is null && adapter.OperationalStatus == OperationalStatus.Up && adapter.NetworkInterfaceType != NetworkInterfaceType.Tunnel && adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback)
            {
                foreach (UnicastIPAddressInformation uni in adapter.GetIPProperties().UnicastAddresses)
                {
                    if (addr is null && uni.Address.AddressFamily == AddressFamily.InterNetwork)
                        addr = uni;
                }
            }
        }

        return addr;
    }

    public static IPAddress? GetLocalIPAddress()
    {
        return GetLocalIPInformations()?.Address;
    }

    public static IPAddress? GetLocalIPv4Mask()
    {
        return GetLocalIPInformations()?.IPv4Mask;
    }

    public static IPAddress GetLocalBoradcastIP(UnicastIPAddressInformation ipInfo)
    {
        IPAddress? ip = null;
        byte[] myIPBytes = ipInfo.Address.GetAddressBytes();
        byte[] subnetBytes = ipInfo.IPv4Mask.GetAddressBytes();
        byte[] broadcastBytes = new byte[myIPBytes.Length];

        for (int i = 0, loopTo = subnetBytes.Length - 1; i <= loopTo; i++)
            broadcastBytes[i] = (byte)(myIPBytes[i] | ~subnetBytes[i]);

        ip = new IPAddress(broadcastBytes);

        return ip;
    }
}