package main

import (
	"flag"
	"io"
	"log"
	"net"
	"net/http"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/net/http2"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/examples/route_guide/routeguide"
)

const (
	requestCount = 1000000
)

func main() {
	addr := flag.String("addr", "127.0.0.1:8080", "Server address")
	useGRPC := flag.Bool("grpc", true, "Use gRPC http/2 implementation")
	flag.Parse()

	http2.VerboseLogs = true

	ctx := context.Background()

	if !*useGRPC {
		tr := &http2.Transport{}
		c, err := net.Dial("tcp", *addr)
		if err != nil {
			log.Fatalf("Dial err=%q", err)
		}
		cc, err := tr.NewClientConn(c)
		if err != nil {
			log.Fatalf("NewClientConn err=%q", err)
		}

		for i := 0; i < requestCount; i++ {
			req, err := http.NewRequest("POST",
				(&url.URL{
					Scheme: "http",
					Host:   *addr,
					Path:   "/routeguide.RouteGuide/ListFeatures",
				}).String(),
				strings.NewReader("\x00\x00\x00\x00\x00"))
			if err != nil {
				log.Fatalf("NewRequest err=%q", err)
			}
			req.Header.Set("Content-Type", "application/grpc")
			req.Header.Set("User-Agent", "grpc-go/0.11")
			req.Header.Set("Te", "trailers")
			req.Header.Set("Grpc-Timeout", "999602u")

			resp, err := cc.RoundTrip(req)
			if err != nil {
				log.Fatalf("RoundTrip err=%q", err)
			}
			log.Printf("status=%d", resp.StatusCode)

			for k, v := range resp.Header {
				log.Printf("k=%q v=%q", k, v)
			}

			n, err := io.ReadFull(resp.Body, make([]byte, 20<<10))
			if err != nil && err != io.ErrUnexpectedEOF {
				log.Fatalf("Read err=%q", err)
			}
			log.Printf("i=%d n=%d", i, n)

			err = resp.Body.Close()
			if err != nil {
				log.Printf("Close err=%q", err)
			}
		}

		return
	}

	cc, err := grpc.Dial(*addr, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("Dial err=%q", err)
	}
	cl := routeguide.NewRouteGuideClient(cc)

	for i := 0; i < requestCount; i++ {
		ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
		fire, err := cl.ListFeatures(ctx, &routeguide.Rectangle{})
		if err != nil {
			log.Fatalf("ListFeatures err=%q", err)
		}

		j := 0
	loop:
		for ; j < 2; j++ {
			_, err := fire.Recv()
			if err != nil {
				if err == io.EOF {
					break loop
				}
				switch grpc.Code(err) {
				case codes.DeadlineExceeded:
					break loop
				default:
					log.Fatalf("Recv err=%q", err)
				}
			}
		}
		log.Printf("i=%d j=%d", i, j)

		if true {
			cancel()
		}

		<-ctx.Done()
	}
}
