// 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 (
	"bytes"
	"context"
	"fmt"
	"html/template"
	"net/http"
	"sort"
	"strings"
	"time"

	"golang.org/x/tools/internal/telemetry"
)

var traceTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
{{define "title"}}Trace Information{{end}}
{{define "body"}}
	{{range .Traces}}<a href="/trace/{{.Name}}">{{.Name}}</a> last: {{.Last.Duration}}, longest: {{.Longest.Duration}}<br>{{end}}
	{{if .Selected}}
		<H2>{{.Selected.Name}}</H2>
		{{if .Selected.Last}}<H3>Last</H3><ul>{{template "details" .Selected.Last}}</ul>{{end}}
		{{if .Selected.Longest}}<H3>Longest</H3><ul>{{template "details" .Selected.Longest}}</ul>{{end}}
	{{end}}
{{end}}
{{define "details"}}
	<li>{{.Offset}} {{.Name}} {{.Duration}} {{.Tags}}</li>
	{{if .Events}}<ul class=events>{{range .Events}}<li>{{.Offset}} {{.Tags}}</li>{{end}}</ul>{{end}}
	{{if .Children}}<ul>{{range .Children}}{{template "details" .}}{{end}}</ul>{{end}}
{{end}}
`))

type traces struct {
	sets       map[string]*traceSet
	unfinished map[telemetry.SpanContext]*traceData
}

type traceResults struct {
	Traces   []*traceSet
	Selected *traceSet
}

type traceSet struct {
	Name    string
	Last    *traceData
	Longest *traceData
}

type traceData struct {
	TraceID  telemetry.TraceID
	SpanID   telemetry.SpanID
	ParentID telemetry.SpanID
	Name     string
	Start    time.Time
	Finish   time.Time
	Offset   time.Duration
	Duration time.Duration
	Tags     string
	Events   []traceEvent
	Children []*traceData
}

type traceEvent struct {
	Time   time.Time
	Offset time.Duration
	Tags   string
}

func (t *traces) StartSpan(ctx context.Context, span *telemetry.Span) {
	if t.sets == nil {
		t.sets = make(map[string]*traceSet)
		t.unfinished = make(map[telemetry.SpanContext]*traceData)
	}
	// just starting, add it to the unfinished map
	td := &traceData{
		TraceID:  span.ID.TraceID,
		SpanID:   span.ID.SpanID,
		ParentID: span.ParentID,
		Name:     span.Name,
		Start:    span.Start,
		Tags:     renderTags(span.Tags),
	}
	t.unfinished[span.ID] = td
	// and wire up parents if we have them
	if !span.ParentID.IsValid() {
		return
	}
	parentID := telemetry.SpanContext{TraceID: span.ID.TraceID, SpanID: span.ParentID}
	parent, found := t.unfinished[parentID]
	if !found {
		// trace had an invalid parent, so it cannot itself be valid
		return
	}
	parent.Children = append(parent.Children, td)
}

func (t *traces) FinishSpan(ctx context.Context, span *telemetry.Span) {
	// finishing, must be already in the map
	td, found := t.unfinished[span.ID]
	if !found {
		return // if this happens we are in a bad place
	}
	delete(t.unfinished, span.ID)

	td.Finish = span.Finish
	td.Duration = span.Finish.Sub(span.Start)
	td.Events = make([]traceEvent, len(span.Events))
	for i, event := range span.Events {
		td.Events[i] = traceEvent{
			Time: event.At,
			Tags: renderTags(event.Tags),
		}
	}

	set, ok := t.sets[span.Name]
	if !ok {
		set = &traceSet{Name: span.Name}
		t.sets[span.Name] = set
	}
	set.Last = td
	if set.Longest == nil || set.Last.Duration > set.Longest.Duration {
		set.Longest = set.Last
	}
	if !td.ParentID.IsValid() {
		fillOffsets(td, td.Start)
	}
}

func (t *traces) Log(ctx context.Context, event telemetry.Event) {}

func (t *traces) Metric(ctx context.Context, data telemetry.MetricData) {}

func (t *traces) Flush() {}

func (t *traces) getData(req *http.Request) interface{} {
	if len(t.sets) == 0 {
		return nil
	}
	data := traceResults{}
	data.Traces = make([]*traceSet, 0, len(t.sets))
	for _, set := range t.sets {
		data.Traces = append(data.Traces, set)
	}
	sort.Slice(data.Traces, func(i, j int) bool { return data.Traces[i].Name < data.Traces[j].Name })
	if bits := strings.SplitN(req.URL.Path, "/trace/", 2); len(bits) > 1 {
		data.Selected = t.sets[bits[1]]
	}
	return data
}

func fillOffsets(td *traceData, start time.Time) {
	td.Offset = td.Start.Sub(start)
	for i := range td.Events {
		td.Events[i].Offset = td.Events[i].Time.Sub(start)
	}
	for _, child := range td.Children {
		fillOffsets(child, start)
	}
}

func renderTags(tags telemetry.TagList) string {
	buf := &bytes.Buffer{}
	for _, tag := range tags {
		fmt.Fprintf(buf, "%v=%q ", tag.Key, tag.Value)
	}
	return buf.String()
}
