package ssdp

import (
	
	
	

	
)

// AnnounceAlive sends ssdp:alive message.
// location should be a string or a ssdp.LocationProvider.
func (,  string,  any,  string,  int,  string,  ...Option) error {
	,  := toLocationProvider()
	if  != nil {
		return 
	}
	,  := opts2config()
	if  != nil {
		return 
	}
	// dial multicast UDP packet.
	,  := multicast.Listen(&multicast.AddrResolver{Addr: }, .multicastConfig.options()...)
	if  != nil {
		return 
	}
	defer .Close()
	// build and send message.
	,  := multicast.SendAddr()
	if  != nil {
		return 
	}
	 := &aliveDataProvider{
		host:     ,
		nt:       ,
		usn:      ,
		location: ,
		server:   ,
		maxAge:   ,
	}
	if ,  := .WriteTo(, );  != nil {
		return 
	}
	return nil
}

type aliveDataProvider struct {
	host     net.Addr
	nt       string
	usn      string
	location LocationProvider
	server   string
	maxAge   int
}

func ( *aliveDataProvider) ( *net.Interface) []byte {
	return buildAlive(.host, .nt, .usn, .location.Location(nil, ), .server, .maxAge)
}

var _ multicast.DataProvider = (*aliveDataProvider)(nil)

func buildAlive( net.Addr, , , ,  string,  int) []byte {
	// bytes.Buffer#Write() is never fail, so we can omit error checks.
	 := new(bytes.Buffer)
	.WriteString("NOTIFY * HTTP/1.1\r\n")
	fmt.Fprintf(, "HOST: %s\r\n", .String())
	fmt.Fprintf(, "NT: %s\r\n", )
	fmt.Fprintf(, "NTS: %s\r\n", "ssdp:alive")
	fmt.Fprintf(, "USN: %s\r\n", )
	if  != "" {
		fmt.Fprintf(, "LOCATION: %s\r\n", )
	}
	if  != "" {
		fmt.Fprintf(, "SERVER: %s\r\n", )
	}
	fmt.Fprintf(, "CACHE-CONTROL: max-age=%d\r\n", )
	.WriteString("\r\n")
	return .Bytes()
}

// AnnounceBye sends ssdp:byebye message.
func (, ,  string,  ...Option) error {
	,  := opts2config()
	if  != nil {
		return 
	}
	// dial multicast UDP packet.
	,  := multicast.Listen(&multicast.AddrResolver{Addr: }, .multicastConfig.options()...)
	if  != nil {
		return 
	}
	defer .Close()
	// build and send message.
	,  := multicast.SendAddr()
	if  != nil {
		return 
	}
	,  := buildBye(, , )
	if  != nil {
		return 
	}
	if ,  := .WriteTo(multicast.BytesDataProvider(), );  != nil {
		return 
	}
	return nil
}

func buildBye( net.Addr, ,  string) ([]byte, error) {
	 := new(bytes.Buffer)
	// FIXME: error should be checked.
	.WriteString("NOTIFY * HTTP/1.1\r\n")
	fmt.Fprintf(, "HOST: %s\r\n", .String())
	fmt.Fprintf(, "NT: %s\r\n", )
	fmt.Fprintf(, "NTS: %s\r\n", "ssdp:byebye")
	fmt.Fprintf(, "USN: %s\r\n", )
	.WriteString("\r\n")
	return .Bytes(), nil
}