// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package debug

import (
	"context"
	"fmt"
	"html/template"
	"net/http"
	"sort"
	"sync"
	"time"

	"golang.org/x/tools/internal/lsp/debug/tag"
	"golang.org/x/tools/internal/telemetry/event"
	"golang.org/x/tools/internal/telemetry/export"
)

var rpcTmpl = template.Must(template.Must(baseTemplate.Clone()).Parse(`
{{define "title"}}RPC Information{{end}}
{{define "body"}}
	<H2>Inbound</H2>
	{{template "rpcSection" .Inbound}}
	<H2>Outbound</H2>
	{{template "rpcSection" .Outbound}}
{{end}}
{{define "rpcSection"}}
	{{range .}}<P>
		<b>{{.Method}}</b> {{.Started}} <a href="/trace/{{.Method}}">traces</a> ({{.InProgress}} in progress)
		<br>
		<i>Latency</i> {{with .Latency}}{{.Mean}} ({{.Min}}<{{.Max}}){{end}}
		<i>By bucket</i> 0s {{range .Latency.Values}}{{if gt .Count 0}}<b>{{.Count}}</b> {{.Limit}} {{end}}{{end}}
		<br>
		<i>Received</i> {{.Received}} (avg. {{.ReceivedMean}})
		<i>Sent</i> {{.Sent}} (avg. {{.SentMean}})
		<br>
		<i>Result codes</i> {{range .Codes}}{{.Key}}={{.Count}} {{end}}
		</P>
	{{end}}
{{end}}
`))

type rpcs struct {
	mu       sync.Mutex
	Inbound  []*rpcStats // stats for incoming lsp rpcs sorted by method name
	Outbound []*rpcStats // stats for outgoing lsp rpcs sorted by method name
}

type rpcStats struct {
	Method    string
	Started   int64
	Completed int64

	Latency  rpcTimeHistogram
	Received byteUnits
	Sent     byteUnits
	Codes    []*rpcCodeBucket
}

type rpcTimeHistogram struct {
	Sum    timeUnits
	Count  int64
	Min    timeUnits
	Max    timeUnits
	Values []rpcTimeBucket
}

type rpcTimeBucket struct {
	Limit timeUnits
	Count int64
}

type rpcCodeBucket struct {
	Key   string
	Count int64
}

func (r *rpcs) ProcessEvent(ctx context.Context, ev event.Event, tagMap event.TagMap) context.Context {
	r.mu.Lock()
	defer r.mu.Unlock()
	switch {
	case ev.IsStartSpan():
		if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
			stats.Started++
		}
	case ev.IsEndSpan():
		span, stats := r.getRPCSpan(ctx, ev)
		if stats != nil {
			endRPC(ctx, ev, span, stats)
		}
	case ev.IsRecord():
		sent := byteUnits(tag.SentBytes.Get(tagMap))
		rec := byteUnits(tag.ReceivedBytes.Get(tagMap))
		if sent != 0 || rec != 0 {
			if _, stats := r.getRPCSpan(ctx, ev); stats != nil {
				stats.Sent += sent
				stats.Received += rec
			}
		}
	}
	return ctx
}

func endRPC(ctx context.Context, ev event.Event, span *export.Span, stats *rpcStats) {
	// update the basic counts
	stats.Completed++

	// get and record the status code
	if status := getStatusCode(span); status != "" {
		var b *rpcCodeBucket
		for c, entry := range stats.Codes {
			if entry.Key == status {
				b = stats.Codes[c]
				break
			}
		}
		if b == nil {
			b = &rpcCodeBucket{Key: status}
			stats.Codes = append(stats.Codes, b)
			sort.Slice(stats.Codes, func(i int, j int) bool {
				return stats.Codes[i].Key < stats.Codes[j].Key
			})
		}
		b.Count++
	}

	// calculate latency if this was an rpc span
	elapsedTime := span.Finish().At.Sub(span.Start().At)
	latencyMillis := timeUnits(elapsedTime) / timeUnits(time.Millisecond)
	if stats.Latency.Count == 0 {
		stats.Latency.Min = latencyMillis
		stats.Latency.Max = latencyMillis
	} else {
		if stats.Latency.Min > latencyMillis {
			stats.Latency.Min = latencyMillis
		}
		if stats.Latency.Max < latencyMillis {
			stats.Latency.Max = latencyMillis
		}
	}
	stats.Latency.Count++
	stats.Latency.Sum += latencyMillis
	for i := range stats.Latency.Values {
		if stats.Latency.Values[i].Limit > latencyMillis {
			stats.Latency.Values[i].Count++
			break
		}
	}
}

func (r *rpcs) getRPCSpan(ctx context.Context, ev event.Event) (*export.Span, *rpcStats) {
	// get the span
	span := export.GetSpan(ctx)
	if span == nil {
		return nil, nil
	}
	// use the span start event look up the correct stats block
	// we do this because it prevents us matching a sub span
	return span, r.getRPCStats(span.Start())
}

func (r *rpcs) getRPCStats(tagMap event.TagMap) *rpcStats {
	method := tag.Method.Get(tagMap)
	if method == "" {
		return nil
	}
	set := &r.Inbound
	if tag.RPCDirection.Get(tagMap) != tag.Inbound {
		set = &r.Outbound
	}
	// get the record for this method
	index := sort.Search(len(*set), func(i int) bool {
		return (*set)[i].Method >= method
	})

	if index < len(*set) && (*set)[index].Method == method {
		return (*set)[index]
	}

	old := *set
	*set = make([]*rpcStats, len(old)+1)
	copy(*set, old[:index])
	copy((*set)[index+1:], old[index:])
	stats := &rpcStats{Method: method}
	stats.Latency.Values = make([]rpcTimeBucket, len(millisecondsDistribution))
	for i, m := range millisecondsDistribution {
		stats.Latency.Values[i].Limit = timeUnits(m)
	}
	(*set)[index] = stats
	return stats
}

func (s *rpcStats) InProgress() int64       { return s.Started - s.Completed }
func (s *rpcStats) SentMean() byteUnits     { return s.Sent / byteUnits(s.Started) }
func (s *rpcStats) ReceivedMean() byteUnits { return s.Received / byteUnits(s.Started) }

func (h *rpcTimeHistogram) Mean() timeUnits { return h.Sum / timeUnits(h.Count) }

func getStatusCode(span *export.Span) string {
	for _, ev := range span.Events() {
		if status := tag.StatusCode.Get(ev); status != "" {
			return status
		}
	}
	return ""
}

func (r *rpcs) getData(req *http.Request) interface{} {
	return r
}

func units(v float64, suffixes []string) string {
	s := ""
	for _, s = range suffixes {
		n := v / 1000
		if n < 1 {
			break
		}
		v = n
	}
	return fmt.Sprintf("%.2f%s", v, s)
}

type timeUnits float64

func (v timeUnits) String() string {
	v = v * 1000 * 1000
	return units(float64(v), []string{"ns", "μs", "ms", "s"})
}

type byteUnits float64

func (v byteUnits) String() string {
	return units(float64(v), []string{"B", "KB", "MB", "GB", "TB"})
}
