package dns

import (
	"errors"
	"net"
	"strings"
	"time"

	"github.com/patrickmn/go-cache"
)

const (
	// TXT record name that lookupRepoTXT will try to lookup.
	TxtRepoRecord = "_rio-pages."

	// The key that the TXT record will have to start with, e.g.
	// "repo=some-random-repo".
	TxtRepoKey = "repo="
)

var (
	// Cache for CNAME resolution results.
	cnameCache = cache.New(1*time.Hour, 1*time.Hour)

	// Cache for TXT resolution results.
	txtRepoCache = cache.New(1*time.Hour, 1*time.Hour)
)

// Query the domain for the a repository redirect.
// Returns the new repository name or "", if we could not
// resolve a repository redirect.
func LookupRepoTXT(domain string) (string, error) {
	repoLookup, found := txtRepoCache.Get(domain)
	if found {
		return repoLookup.(string), nil
	}

	txts, err := net.LookupTXT("_rio-pages." + domain)
	if err != nil {
		return "", err
	}

	repo := ""
	for _, txt := range txts {
		if !strings.HasPrefix(txt, TxtRepoKey) {
			continue
		}

		repo = strings.TrimPrefix(txt, TxtRepoKey)
		break
	}

	txtRepoCache.Set(domain, repo, cache.DefaultExpiration)
	return repo, nil
}

// Query the domain for a CNAME record. Returns the resolved
// CNAME or "", if no CNAME could be queried.
func LookupCNAME(domain string) (string, error) {
	cname, found := cnameCache.Get(domain)
	if found {
		if cname == "" {
			return "", errors.New("Previous request failure")
		}

		return cname.(string), nil
	}

	cname, err := net.LookupCNAME(domain)
	if err == nil {
		cnameCache.Set(domain, cname, cache.DefaultExpiration)
		return cname.(string), nil
	}

	cnameCache.Set(domain, "", cache.DefaultExpiration)
	return "", err
}
