package clientutil

import (
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"
)

func testHTTPServer() *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		io.WriteString(w, "OK")
	}))
}

type testBackends struct {
	servers []*httptest.Server
	addrs   []string
}

func newTestBackends(n int) *testBackends {
	b := new(testBackends)
	for i := 0; i < n; i++ {
		s := testHTTPServer()
		u, _ := url.Parse(s.URL)
		b.servers = append(b.servers, s)
		b.addrs = append(b.addrs, u.Host)
	}
	return b
}

func (b *testBackends) ResolveIPs(_ []string) []string {
	return b.addrs
}

func (b *testBackends) stop(i int) {
	b.servers[i].Close()
}

func (b *testBackends) close() {
	for _, s := range b.servers {
		s.Close()
	}
}

func doRequests(backends *testBackends, u string, n int) (int, int) {
	c := &http.Client{
		Transport: NewTransport([]string{"backend"}, nil, backends),
	}
	b := NewExponentialBackOff()

	var errs, oks int
	for i := 0; i < n; i++ {
		req, _ := http.NewRequest("GET", u, nil)
		resp, err := RetryHTTPDo(c, req, b)
		if err != nil {
			errs++
			continue
		}
		ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		oks++
	}

	return oks, errs
}

func TestRetryAndTransport(t *testing.T) {
	b := newTestBackends(3)
	defer b.close()

	oks, errs := doRequests(b, "http://backend/", 100)
	if errs > 0 {
		t.Fatalf("errs=%d", errs)
	}
	if oks == 0 {
		t.Fatal("oks=0")
	}

	b.stop(0)

	oks, errs = doRequests(b, "http://backend/", 100)
	if errs > 0 {
		t.Fatalf("errs=%d", errs)
	}
	if oks == 0 {
		t.Fatal("oks=0")
	}
}