package fr.insa.clavardator.client.network;

import fr.insa.clavardator.lib.util.Log;

import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;

public class NetUtil {
	/**
	 * Lists all ipv4 broadcast addresses
	 *
	 * @return
	 * @throws SocketException
	 */
	public static List<InetAddress> listAllBroadcastAddresses() throws SocketException {
		List<InetAddress> broadcastList = new ArrayList<>();
		final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

		while (interfaces.hasMoreElements()) {
			NetworkInterface networkInterface = interfaces.nextElement();
			if (!networkInterface.isLoopback() && networkInterface.isUp()) {
				networkInterface.getInterfaceAddresses().stream()
						.map(InterfaceAddress::getBroadcast)
						.filter(Objects::nonNull)
						.forEach(broadcastList::add);
			}
		}
		return broadcastList;
	}

	/**
	 * Lists all local Ipv4 addresses
	 *
	 * @return
	 * @throws SocketException
	 */
	public static List<InetAddress> listAllLocalAddresses() throws SocketException {
		List<InetAddress> localList = new ArrayList<>();
		final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

		while (interfaces.hasMoreElements()) {
			NetworkInterface networkInterface = interfaces.nextElement();
			if (!networkInterface.isLoopback() && networkInterface.isUp()) {
				networkInterface.getInterfaceAddresses().stream()
						.filter((i) -> Objects.nonNull(i.getBroadcast()))
						.map(InterfaceAddress::getAddress)
						.filter(Objects::nonNull)
						.forEach(localList::add);
			}
		}
		Log.v("NetUtil", "Local addresses: " + Arrays.toString(new List[]{localList}));
		return localList;
	}

	public static boolean isLocalAddress(InetAddress address) throws SocketException {
		final List<InetAddress> list = listAllLocalAddresses();
		return list.stream().anyMatch((a) -> Arrays.equals(address.getAddress(), a.getAddress()));
	}
}
