package server

import (
	"net"
	"runtime"

	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
)

// UDPHandler udp handler
type UDPHandler interface {
	Handler(*net.UDPConn)
}

// UDPServer udp server
type UDPServer struct {
	addr    *addr
	handler UDPHandler
}

// Start udp server start
func (us *UDPServer) Start() error {
	if us.handler == nil {
		return errorf(errUDPHandlerNotRegisterd)
	}
	var ln *net.UDPConn
	var err error
	a, err := net.ResolveUDPAddr("udp", us.addr.internalIp)
	if err != nil {
		return err
	}
	ln, err = net.ListenUDP("udp", a)
	if err != nil {
		return errorf(errUDPListenFailed, us.addr, err)
	}
	Log.Infof("UDP Server Listen on %s", us.addr)
	if err := setUDPSocketOptions(ln); err != nil {
		return err
	}
	go us.handler.Handler(ln)
	return nil
}
func setUDPSocketOptions(conn *net.UDPConn) error {
	if runtime.GOOS == "windows" {
		return nil
	}
	if ip4 := conn.LocalAddr().(*net.UDPAddr).IP.To4(); ip4 != nil {
		return ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
	}
	return ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
}
