package dht

import (
	"net"
	"time"

	log "github.com/sirupsen/logrus"

	"github.com/vapor/consensus"
	"github.com/vapor/errors"
)

var (
	errInvalidIP     = errors.New("invalid ip address")
	errDNSTimeout    = errors.New("get dns seed timeout")
	errDNSSeedsEmpty = errors.New("dns seeds is empty")

	dnsTimeout = 5 * time.Second
)

// QueryDNSSeeds Query the DNS seeds.
func QueryDNSSeeds(lookupHost func(host string) (addrs []string, err error)) ([]string, error) {
	if len(consensus.ActiveNetParams.DNSSeeds) == 0 {
		return nil, errDNSSeedsEmpty
	}

	resultCh := make(chan *[]string, 1)
	for _, dnsSeed := range consensus.ActiveNetParams.DNSSeeds {
		go queryDNSSeeds(lookupHost, resultCh, dnsSeed, consensus.ActiveNetParams.DefaultPort)
	}

	select {
	case result := <-resultCh:
		return *result, nil
	case <-time.After(dnsTimeout):
		return nil, errDNSTimeout
	}
}

func queryDNSSeeds(lookupHost func(host string) (addrs []string, err error), resultCh chan *[]string, dnsSeed, port string) {
	var seeds []string

	//TODO add proxy
	addrs, err := lookupHost(dnsSeed)
	if err != nil {
		log.WithFields(log.Fields{"module": logModule, "err": err, "dnsSeed": dnsSeed}).Error("fail on look up host")
		return
	}

	for _, addr := range addrs {
		if ip := net.ParseIP(addr); ip == nil {
			log.WithFields(log.Fields{"module": logModule, "err": errInvalidIP, "dnsSeed": dnsSeed}).Error("fail on parse IP")
			return
		}

		seeds = append(seeds, net.JoinHostPort(addr, port))
	}
	if len(seeds) == 0 {
		return
	}
	//if channel is full, drop it
	select {
	case resultCh <- &seeds:
	default:
	}
}
