package main

import (
	"net"
	"time"

	"github.com/hoisie/redis"
)

type Hosts struct {
	providers []HostProvider
	refreshInterval time.Duration
}

type HostProvider interface {
	Get(domain string) ([]string, bool)
	Refresh()
}

func NewHosts(hs HostsSettings, rs RedisSettings) Hosts {
	providers := []HostProvider{
		NewFileProvider(hs.HostsFile),
	}

	if hs.RedisEnable {
		rc := &redis.Client{Addr: rs.Addr(), Db: rs.DB, Password: rs.Password}

		providers = append(providers, NewRedisProvider(rc, hs.RedisKey))
	}

	return Hosts{providers, time.Second * time.Duration(hs.RefreshInterval)}
}

func (h *Hosts) refresh() {
	ticker := time.NewTicker(h.refreshInterval)

	go func() {
		for {
			// Force a refresh every refreshInterval
			for _, provider := range h.providers {
				provider.Refresh()
			}

			<-ticker.C
		}
	}()
}

/*
Match local /etc/hosts file first, remote redis records second
*/
func (h *Hosts) Get(domain string, family int) ([]net.IP, bool) {
	var sips []string
	var ok bool
	var ip net.IP
	var ips []net.IP

	for _, provider := range h.providers {
		sips, ok = provider.Get(domain)

		if ok {
			break
		}
	}

	if sips == nil {
		return nil, false
	}

	for _, sip := range sips {
		switch family {
		case _IP4Query:
			ip = net.ParseIP(sip).To4()
		case _IP6Query:
			ip = net.ParseIP(sip).To16()
		default:
			continue
		}
		if ip != nil {
			ips = append(ips, ip)
		}
	}

	return ips, ips != nil
}