package multicast

import (
	
)

type InterfacesProviderFunc func() []net.Interface

// InterfacesProvider specify a function to list all interfaces to multicast.
// If no provider are given, all possible interfaces will be used.
var InterfacesProvider InterfacesProviderFunc

// SystemAssignedInterface indicates use the system assigned multicast interface or not.
// InterfacesProvider will be ignored when this is true.
var SystemAssignedInterface bool = false

// interfaces gets list of net.Interface to multicast UDP packet.
func interfaces() ([]net.Interface, error) {
	if  := InterfacesProvider;  != nil {
		if  := (); len() > 0 {
			return , nil
		}
	}
	return interfacesIPv4()
}

// interfacesIPv4 lists net.Interface on IPv4.
func interfacesIPv4() ([]net.Interface, error) {
	,  := net.Interfaces()
	if  != nil {
		return nil, 
	}
	 := make([]net.Interface, 0, len())
	for ,  := range  {
		if !hasLinkUp(&) || !hasMulticast(&) || !hasIPv4Address(&) {
			continue
		}
		 = append(, )
	}
	return , nil
}

// hasLinkUp checks an I/F have link-up or not.
func hasLinkUp( *net.Interface) bool {
	return .Flags&net.FlagUp != 0
}

// hasMulticast checks an I/F supports multicast or not.
func hasMulticast( *net.Interface) bool {
	return .Flags&net.FlagMulticast != 0
}

// hasIPv4Address checks an I/F have IPv4 address.
func hasIPv4Address( *net.Interface) bool {
	,  := .Addrs()
	if  != nil {
		return false
	}
	for ,  := range  {
		, ,  := net.ParseCIDR(.String())
		if  != nil {
			continue
		}
		if len(.To4()) == net.IPv4len && !.IsUnspecified() {
			return true
		}
	}
	return false
}