// Copyright 2015 The Vanadium 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 browseserver provides a web interface that can be used to interact with the
// vanadium debug interface.
package browseserver

import (
	"bytes"
	"errors"
	"fmt"
	"html"
	"html/template"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc/reserved"
	"v.io/v23/security"
	"v.io/v23/services/logreader"
	"v.io/v23/services/stats"
	svtrace "v.io/v23/services/vtrace"
	"v.io/v23/syncbase"
	"v.io/v23/uniqueid"
	"v.io/v23/verror"
	"v.io/v23/vom"
	"v.io/v23/vtrace"
	"v.io/x/ref/services/debug/debug/browseserver/sbtree"
	"v.io/x/ref/services/internal/pproflib"
	"v.io/x/ref/services/syncbase/fake"
)

//go:generate ./gen_assets.sh

const browseProfilesPath = "/profiles"

const (
	allTraceTmpl   = "alltrace.html"
	blessingsTmpl  = "blessings.html"
	chromeTmpl     = "chrome.html"
	globTmpl       = "glob.html"
	logsTmpl       = "logs.html"
	profilesTmpl   = "profiles.html"
	resolveTmpl    = "resolve.html"
	statsTmpl      = "stats.html"
	vtraceTmpl     = "vtrace.html"
	syncbaseTmpl   = "syncbase.html"
	noSyncbaseTmpl = "no_syncbase.html"
	collectionTmpl = "collection.html"
)

// Serve serves the debug interface over http.  An HTTP server is started (serving at httpAddr), its
// various handlers make rpc calls to the given name to gather debug information.  If log is true
// we additionally log debug information for these rpc requests.  Timeout defines the timeout for the
// rpc calls.  The HTTPServer will run until the passed context is canceled.
func Serve(ctx *context.T, httpAddr, name string, timeout time.Duration, log bool, assetDir string) error {
	mux, err := CreateServeMux(ctx, timeout, log, assetDir, "")
	if err != nil {
		return err
	}
	if len(httpAddr) == 0 {
		httpAddr = "127.0.0.1:0"
	}
	ln, err := net.Listen("tcp", httpAddr)
	if err != nil {
		return err
	}
	go func() {
		url := "http://" + ln.Addr().String() + "/?n=" + url.QueryEscape(name)
		fmt.Printf("Visit %s and Ctrl-C to quit\n", url)
		// Open the browser if we can
		switch runtime.GOOS {
		case "linux":
			exec.Command("xdg-open", url).Start()
		case "darwin":
			exec.Command("open", url).Start()
		}

		<-ctx.Done()
		ln.Close()
	}()
	return http.Serve(ln, mux)
}

// CreateServeMux returns a ServeMux object that has handlers set up.
func CreateServeMux(ctx *context.T, timeout time.Duration, log bool, assetDir, urlPrefix string) (*http.ServeMux, error) {
	mux := http.NewServeMux()
	h, err := newHandler(ctx, timeout, log, assetDir, urlPrefix)
	if err != nil {
		return nil, err
	}
	mux.Handle("/", &resolveHandler{h})
	mux.Handle("/name", &resolveHandler{h})
	mux.Handle("/stats", &statsHandler{h})
	mux.Handle("/blessings", &blessingsHandler{h})
	mux.Handle("/logs", &logsHandler{h})
	mux.Handle("/glob", &globHandler{h})
	mux.Handle(browseProfilesPath, &profilesHandler{h})
	mux.Handle(browseProfilesPath+"/", &profilesHandler{h})
	mux.Handle("/vtraces", &allTracesHandler{h})
	mux.Handle("/vtrace", &vtraceHandler{h})
	mux.Handle("/syncbase", &syncbaseHandler{h})
	mux.Handle("/syncbase/collection", &collectionHandler{h})
	mux.Handle("/favicon.ico", http.NotFoundHandler())

	return mux, nil
}

type handler struct {
	ctx       *context.T
	timeout   time.Duration
	log       bool
	urlPrefix string
	file      func(name string) ([]byte, error)
	cacheMap  map[string]*template.Template
	funcs     template.FuncMap
}

func newHandler(ctx *context.T, timeout time.Duration, log bool, assetDir, urlPrefix string) (*handler, error) {
	h := &handler{
		ctx:       ctx,
		timeout:   timeout,
		log:       log,
		urlPrefix: urlPrefix,
	}
	colors := []string{"red", "blue", "green"}
	pos := 0
	h.funcs = template.FuncMap{
		"verrorID":           verror.ErrorID,
		"unmarshalPublicKey": security.UnmarshalPublicKey,
		"endpoint": func(n string) (naming.Endpoint, error) {
			if naming.Rooted(n) {
				n, _ = naming.SplitAddressName(n)
			}
			return naming.ParseEndpoint(n)
		},
		"endpointName": func(ep naming.Endpoint) string { return ep.Name() },
		"goValueFromVOM": func(v *vom.RawBytes) interface{} {
			var ret interface{}
			if err := v.ToValue(&ret); err != nil {
				panic(err)
			}
			return ret
		},
		"nextColor": func() string {
			c := colors[pos]
			pos = (pos + 1) % len(colors)
			return c
		},
	}

	if assetDir == "" {
		h.file = Asset
		h.cacheMap = make(map[string]*template.Template)
		all := []string{chromeTmpl, allTraceTmpl, blessingsTmpl, globTmpl,
			logsTmpl, profilesTmpl, resolveTmpl, statsTmpl, vtraceTmpl,
			syncbaseTmpl, noSyncbaseTmpl}
		for _, tmpl := range all {
			if _, err := h.template(ctx, tmpl); err != nil {
				return nil, err
			}
		}
	} else {
		h.file = func(name string) ([]byte, error) {
			return ioutil.ReadFile(filepath.Join(assetDir, name))
		}
	}
	return h, nil
}

func (h *handler) template(ctx *context.T, name string) (t *template.Template, err error) {
	if t = h.cacheMap[name]; t != nil {
		return t, nil
	}
	if name == chromeTmpl {
		t = template.New(name).Funcs(h.funcs)
	} else {
		if t, err = h.template(ctx, chromeTmpl); err != nil {
			return nil, err
		}
		if t, err = t.Clone(); err != nil {
			return nil, err
		}
	}
	src, err := h.file(name)
	if err != nil {
		return nil, err
	}
	if _, err = t.Parse(string(src)); err != nil {
		return nil, err
	}
	return t, nil
}

func (h *handler) execute(ctx *context.T, w http.ResponseWriter, r *http.Request, tmplName string, args interface{}) {
	if h.log {
		ctx.Infof("DEBUG: %q -- %+v", r.URL, args)
	}
	t, err := h.template(ctx, tmplName)
	if err != nil {
		fmt.Fprintf(w, "ERROR:%v", err)
		ctx.Errorf("Error parsing template %q: %v", tmplName, err)
		return
	}
	if err := t.Execute(w, args); err != nil {
		fmt.Fprintf(w, "ERROR:%v", err)
		ctx.Errorf("Error executing template %q: %v", tmplName, err)
		return
	}
}

func (h *handler) withTimeout(ctx *context.T) (*context.T, func()) {
	return context.WithTimeout(ctx, h.timeout)
}

type resolveHandler struct{ *handler }

func (h *resolveHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := r.FormValue("n")
	var suffix string
	ctx, tracer := newTracer(h.ctx)
	timeoutCtx, cancel := h.withTimeout(ctx)
	defer cancel()
	m, err := v23.GetNamespace(ctx).Resolve(timeoutCtx, name)
	if m != nil {
		suffix = m.Name
	}
	args := struct {
		ServerName  string
		CommandLine string
		Vtrace      *Tracer
		MountEntry  *naming.MountEntry
		Error       error
	}{
		ServerName:  strings.TrimSuffix(name, suffix),
		CommandLine: fmt.Sprintf("debug resolve %q", name),
		Vtrace:      tracer,
		MountEntry:  m,
		Error:       err,
	}
	h.execute(h.ctx, w, r, "resolve.html", args)
}

type blessingsHandler struct{ *handler }

func (h *blessingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := r.FormValue("n")
	ctx, tracer := newTracer(h.ctx)
	timeoutCtx, cancel := h.withTimeout(ctx)
	call, err := v23.GetClient(ctx).StartCall(timeoutCtx, name, "DoNotReallyCareAboutTheMethod", nil)
	args := struct {
		ServerName        string
		CommandLine       string
		Vtrace            *Tracer
		Error             error
		Blessings         security.Blessings
		Recognized        []string
		CertificateChains [][]security.Certificate
	}{
		ServerName:  name,
		Vtrace:      tracer,
		CommandLine: fmt.Sprintf("vrpc identify %q", name),
		Error:       err,
	}
	if call != nil {
		args.Recognized, args.Blessings = call.RemoteBlessings()
		args.CertificateChains = security.MarshalBlessings(args.Blessings).CertificateChains
		// Don't actually care about the RPC, so don't bother waiting on the Finish.
		cancel()
		defer func() { go call.Finish() }()
	} else {
		cancel()
	}
	h.execute(h.ctx, w, r, "blessings.html", args)
}

type statsHandler struct{ *handler }

func (h *statsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server      = r.FormValue("n")
		stat        = r.FormValue("s")
		prefix      = naming.Join(server, "__debug", "stats")
		name        = naming.Join(prefix, stat)
		ctx, tracer = newTracer(h.ctx)
		hasValue    = true
	)
	timeoutCtx, cancel := h.withTimeout(ctx)
	defer cancel()
	v, err := stats.StatsClient(name).Value(timeoutCtx)
	if verror.ErrorID(err) == verror.ErrNoExist.ID {
		// Stat does not exist as a value, that's okay.
		err = nil
		hasValue = false
	}
	var children []string
	var childrenErrors []error
	timeoutCtx2, cancel2 := h.withTimeout(ctx)
	defer cancel2()
	if glob, globErr := v23.GetNamespace(ctx).Glob(timeoutCtx2, naming.Join(name, "*")); globErr == nil {
		for e := range glob {
			switch e := e.(type) {
			case *naming.GlobReplyEntry:
				children = append(children, strings.TrimPrefix(e.Value.Name, prefix))
			case *naming.GlobReplyError:
				childrenErrors = append(childrenErrors, e.Value.Error)
			}
		}
		if len(children) == 1 && !hasValue {
			// Single child, save an extra click
			redirect, err := url.Parse(r.URL.String())
			if err == nil {
				q := redirect.Query()
				q.Set("n", server)
				q.Set("s", children[0])
				redirect.RawQuery = q.Encode()
				ctx.Infof("Redirecting from %v to %v", r.URL, redirect)
				redirectString := redirect.String()
				if h.urlPrefix != "" {
					redirectString = fmt.Sprintf("%s/%s", h.urlPrefix, redirectString)
				}
				http.Redirect(w, r, redirectString, http.StatusTemporaryRedirect)
				return
			}
		}
	} else if err == nil {
		err = globErr
	}
	args := struct {
		ServerName     string
		CommandLine    string
		Vtrace         *Tracer
		StatName       string
		Value          *vom.RawBytes
		Children       []string
		ChildrenErrors []error
		Globbed        bool
		Error          error
	}{
		ServerName:     server,
		Vtrace:         tracer,
		StatName:       stat,
		Value:          v,
		Error:          err,
		Children:       children,
		ChildrenErrors: childrenErrors,
		Globbed:        len(children)+len(childrenErrors) > 0,
	}
	if hasValue {
		args.CommandLine = fmt.Sprintf("debug stats watch %q", name)
	} else {
		args.CommandLine = fmt.Sprintf("debug glob %q", naming.Join(name, "*"))
	}
	h.execute(h.ctx, w, r, "stats.html", args)
}

type logsHandler struct{ *handler }

func (h *logsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server = r.FormValue("n")
		log    = r.FormValue("l")
		prefix = naming.Join(server, "__debug", "logs")
		name   = naming.Join(prefix, log)
		path   = strings.TrimPrefix(r.URL.Path, "/")
		list   = func() bool {
			for _, a := range r.Header[http.CanonicalHeaderKey("Accept")] {
				if a == "text/event-stream" {
					return true
				}
			}
			return false
		}()
		ctx, _ = newTracer(h.ctx)
	)
	// The logs handler streams result to the web browser because there
	// have been cases where there are ~1 million log files, so doing this
	// streaming thing will make the UI more responsive.
	//
	// For the same reason, avoid setting a timeout.
	if len(log) == 0 && list {
		w.Header().Add("Content-Type", "text/event-stream")
		glob, err := v23.GetNamespace(ctx).Glob(ctx, naming.Join(name, "*"))
		if err != nil {
			writeErrorEvent(w, err)
			return
		}
		flusher, _ := w.(http.Flusher)
		for e := range glob {
			switch e := e.(type) {
			case *naming.GlobReplyEntry:
				logfile := strings.TrimPrefix(e.Value.Name, prefix+"/")
				writeEvent(w, fmt.Sprintf(
					`<a href="%s?n=%s&l=%s">%s</a>`,
					path,
					url.QueryEscape(server),
					url.QueryEscape(logfile),
					html.EscapeString(logfile)))
			case *naming.GlobReplyError:
				writeErrorEvent(w, e.Value.Error)
			}
			if flusher != nil {
				flusher.Flush()
			}
		}
		return
	}
	if len(log) == 0 {
		args := struct {
			ServerName  string
			CommandLine string
			Vtrace      *Tracer
		}{
			ServerName:  server,
			CommandLine: fmt.Sprintf("debug glob %q", naming.Join(name, "*")),
		}
		h.execute(h.ctx, w, r, "logs.html", args)
		return
	}
	w.Header().Add("Content-Type", "text/plain")
	stream, err := logreader.LogFileClient(name).ReadLog(ctx, 0, logreader.AllEntries, true)
	if err != nil {
		fmt.Fprintf(w, "ERROR(%v): %v\n", verror.ErrorID(err), err)
		return
	}
	var (
		entries   = make(chan logreader.LogEntry)
		abortRPC  = make(chan bool)
		abortHTTP <-chan bool
		errch     = make(chan error, 1) // At most one write on this channel, avoid blocking any goroutines
	)
	if notifier, ok := w.(http.CloseNotifier); ok {
		abortHTTP = notifier.CloseNotify()
	}
	go func() {
		// writes to: entries, errch
		// reads from: abortRPC
		defer stream.Finish()
		defer close(entries)
		iterator := stream.RecvStream()
		for iterator.Advance() {
			select {
			case entries <- iterator.Value():
			case <-abortRPC:
				return
			}
		}
		if err := iterator.Err(); err != nil {
			errch <- err
		}
	}()
	// reads from: entries, errch, abortHTTP
	// writes to: abortRPC
	defer close(abortRPC)
	for {
		select {
		case e, more := <-entries:
			if !more {
				return
			}
			fmt.Fprintln(w, e.Line)
		case err := <-errch:
			fmt.Fprintf(w, "ERROR(%v): %v\n", verror.ErrorID(err), err)
			return
		case <-abortHTTP:
			return
		}
	}
}

type globHandler struct{ *handler }

func (h *globHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	type entry struct {
		Suffix string
		Error  error
	}
	var (
		server      = r.FormValue("n")
		suffix      = r.FormValue("s")
		pattern     = naming.Join(server, suffix, "*")
		ctx, tracer = newTracer(h.ctx)
		entries     []entry
	)
	timeoutCtx, cancel := h.withTimeout(ctx)
	defer cancel()
	ch, err := v23.GetNamespace(ctx).Glob(timeoutCtx, pattern)
	if err != nil {
		entries = append(entries, entry{Error: err})
	}
	if ch != nil {
		for e := range ch {
			switch e := e.(type) {
			case *naming.GlobReplyEntry:
				entries = append(entries, entry{Suffix: strings.TrimPrefix(e.Value.Name, server)})
			case *naming.GlobReplyError:
				entries = append(entries, entry{Error: e.Value.Error})
			}
		}
	}
	args := struct {
		ServerName  string
		CommandLine string
		Vtrace      *Tracer
		Pattern     string
		Entries     []entry
	}{
		ServerName:  server,
		CommandLine: fmt.Sprintf("debug glob %q", pattern),
		Vtrace:      tracer,
		Pattern:     pattern,
		Entries:     entries,
	}
	h.execute(h.ctx, w, r, "glob.html", args)
}

type profilesHandler struct{ *handler }

func (h *profilesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server = r.FormValue("n")
		name   = naming.Join(server, "__debug", "pprof")
	)
	if len(server) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Must specify a server with the URL query parameter 'n'")
		return
	}
	if path := strings.TrimSuffix(r.URL.Path, "/"); strings.HasSuffix(path, strings.TrimSuffix(browseProfilesPath, "/")) {
		urlPrefix := fmt.Sprintf("%s/pprof", strings.TrimPrefix(browseProfilesPath, "/"))
		args := struct {
			ServerName  string
			CommandLine string
			Vtrace      *Tracer
			URLPrefix   string
		}{
			ServerName:  server,
			CommandLine: fmt.Sprintf("debug pprof run %q", name),
			URLPrefix:   urlPrefix,
		}
		h.execute(h.ctx, w, r, "profiles.html", args)
		return
	}
	pproflib.PprofProxy(h.ctx, browseProfilesPath, name).ServeHTTP(w, r)
}

const (
	allTracesLabel       = ">0s"
	oneMsTraceLabel      = ">1ms"
	tenMsTraceLabel      = ">10ms"
	hundredMsTraceLabel  = ">100ms"
	oneSecTraceLabel     = ">1s"
	tenSecTraceLabel     = ">10s"
	hundredSecTraceLabel = ">100s"
)

var (
	labelToCutoff = map[string]float64{
		allTracesLabel:       0,
		oneMsTraceLabel:      0.001,
		tenMsTraceLabel:      0.01,
		hundredMsTraceLabel:  0.1,
		oneSecTraceLabel:     1,
		tenSecTraceLabel:     10,
		hundredSecTraceLabel: 100,
	}
	sortedLabels = []string{allTracesLabel, oneMsTraceLabel, tenMsTraceLabel, hundredMsTraceLabel, oneSecTraceLabel, tenSecTraceLabel, hundredSecTraceLabel}
)

type traceWithStart struct {
	Id    string
	Start time.Time
}

type traceSort []traceWithStart

func (t traceSort) Len() int           { return len(t) }
func (t traceSort) Less(i, j int) bool { return t[i].Start.After(t[j].Start) }
func (t traceSort) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }

func bucketTraces(ctx *context.T, name string) (map[string]traceSort, error) {
	stub := svtrace.StoreClient(name)

	call, err := stub.AllTraces(ctx)
	if err != nil {
		return nil, err
	}
	stream := call.RecvStream()
	var missingTraces []string
	bucketedTraces := map[string]traceSort{}
	for stream.Advance() {
		trace := stream.Value()
		node := vtrace.BuildTree(&trace)
		if node == nil {
			missingTraces = append(missingTraces, trace.Id.String())
			continue
		}
		startTime := findStartTime(node)
		endTime := findEndTime(node)
		traceNode := traceWithStart{Id: trace.Id.String(), Start: startTime}
		duration := endTime.Sub(startTime).Seconds()
		if endTime.IsZero() || startTime.IsZero() {
			// Set the duration so something small but greater than zero so it shows up in
			// the first bucket.
			duration = 0.0001
		}
		for l, cutoff := range labelToCutoff {
			if duration >= cutoff {
				bucketedTraces[l] = append(bucketedTraces[l], traceNode)
			}
		}
	}

	for _, v := range bucketedTraces {
		sort.Sort(v)
	}
	if err := stream.Err(); err != nil {
		return bucketedTraces, err
	}
	if err := call.Finish(); err != nil {
		return bucketedTraces, err
	}
	if len(missingTraces) > 0 {
		return bucketedTraces, fmt.Errorf("missing information for: %s", strings.Join(missingTraces, ","))
	}
	return bucketedTraces, nil
}

type allTracesHandler struct{ *handler }

func (a *allTracesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server = r.FormValue("n")
		name   = naming.Join(server, "__debug", "vtrace")
	)
	if len(server) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Must specify a server with the URL query parameter 'n'")
		return
	}
	ctx, tracer := newTracer(a.ctx)
	buckets, err := bucketTraces(ctx, name)

	data := struct {
		Buckets      map[string]traceSort
		SortedLabels []string
		Err          error
		ServerName   string
		CommandLine  string
		Vtrace       *Tracer
	}{
		Buckets:      buckets,
		SortedLabels: sortedLabels,
		Err:          err,
		CommandLine:  fmt.Sprintf("debug vtraces %q", name),
		ServerName:   server,
		Vtrace:       tracer,
	}
	a.execute(a.ctx, w, r, "alltrace.html", data)
}

type divTree struct {
	Id string
	// Start is a value from 0-100 which is the percentage of time into the parent span's duration
	// that this span started.
	Start int
	// Width is a value from 0-100 which is the percentage of time in the parent span's duration this span
	// took
	Width       int
	Name        string
	Annotations []annotation
	Children    []divTree
}

type annotation struct {
	// Position is a value from 0-100 which is the percentage of time into the span's duration that this
	// annotation occured.
	Position int
	Msg      string
}

func convertToTree(n *vtrace.Node, parentStart time.Time, parentEnd time.Time) *divTree {
	// If either start of end is missing, use the parent start/end.
	startTime := n.Span.Start
	if startTime.IsZero() {
		startTime = parentStart
	}

	endTime := n.Span.End
	if endTime.IsZero() {
		endTime = parentEnd
	}

	parentDuration := parentEnd.Sub(parentStart).Seconds()
	start := int(100 * startTime.Sub(parentStart).Seconds() / parentDuration)
	end := int(100 * endTime.Sub(parentStart).Seconds() / parentDuration)
	width := end - start
	if width == 0 {
		width = 1
	}
	top := &divTree{
		Id:    n.Span.Id.String(),
		Start: start,
		Width: width,
		Name:  n.Span.Name,
	}

	top.Annotations = make([]annotation, len(n.Span.Annotations))
	for i, a := range n.Span.Annotations {
		top.Annotations[i].Msg = a.Message
		if a.When.IsZero() {
			top.Annotations[i].Position = 0
			continue
		}
		top.Annotations[i].Position = int(100*a.When.Sub(parentStart).Seconds()/parentDuration) - start
	}

	top.Children = make([]divTree, len(n.Children))
	for i, c := range n.Children {
		top.Children[i] = *convertToTree(c, startTime, endTime)
	}
	return top

}

// findStartTime returns the start time of a node.  The start time is defined as either the span start if it exists
// or the timestamp of the first annotation/sub span.
func findStartTime(n *vtrace.Node) time.Time {
	if !n.Span.Start.IsZero() {
		return n.Span.Start
	}
	var startTime time.Time
	for _, a := range n.Span.Annotations {
		startTime = a.When
		if !startTime.IsZero() {
			break
		}
	}
	for _, c := range n.Children {
		childStartTime := findStartTime(c)
		if startTime.IsZero() || (!childStartTime.IsZero() && startTime.After(childStartTime)) {
			startTime = childStartTime
		}
		if !startTime.IsZero() {
			break
		}
	}
	return startTime
}

// findEndTime returns the end time of a node.  The end time is defined as either the span end if it exists
// or the timestamp of the last annotation/sub span.
func findEndTime(n *vtrace.Node) time.Time {
	if !n.Span.End.IsZero() {
		return n.Span.End
	}

	size := len(n.Span.Annotations)
	var endTime time.Time
	for i := range n.Span.Annotations {
		endTime = n.Span.Annotations[size-1-i].When
		if !endTime.IsZero() {
			break
		}
	}

	size = len(n.Children)
	for i := range n.Children {
		childEndTime := findEndTime(n.Children[size-1-i])
		if endTime.IsZero() || (!childEndTime.IsZero() && childEndTime.After(endTime)) {
			endTime = childEndTime
		}
		if !endTime.IsZero() {
			break
		}
	}
	return endTime
}

type vtraceHandler struct{ *handler }

func (v *vtraceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server  = r.FormValue("n")
		traceId = r.FormValue("t")
		name    = naming.Join(server, "__debug", "vtrace")
	)

	if len(server) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Must specify a server with the URL query parameter 'n'")
		return
	}

	stub := svtrace.StoreClient(name)
	ctx, tracer := newTracer(v.ctx)
	id, err := uniqueid.FromHexString(traceId)

	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Invalid trace id %s: %v", traceId, err)
		return
	}

	trace, err := stub.Trace(ctx, id)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprintf(w, "Unknown trace id: %s", traceId)
		return
	}

	var buf bytes.Buffer

	vtrace.FormatTrace(&buf, &trace, nil)
	node := vtrace.BuildTree(&trace)

	if node == nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "coud not find root span for trace")
		return
	}

	tree := convertToTree(node, findStartTime(node), findEndTime(node))
	data := struct {
		Id          string
		Root        *divTree
		ServerName  string
		CommandLine string
		DebugTrace  string
		Vtrace      *Tracer
	}{
		Id:          traceId,
		Root:        tree,
		ServerName:  server,
		CommandLine: fmt.Sprintf("debug vtraces %q", name),
		Vtrace:      tracer,
		DebugTrace:  buf.String(),
	}
	v.execute(v.ctx, w, r, "vtrace.html", data)
}

// The syncbaseHandler handles the main Syncbase viewer page is linked from the
// nav bar of the Debug browser. It displays a list of databases and their
// collections, and has links to the detailed collection page.  It supports
// adding a "&fake=true" query argument to inject a fake Syncbase service.
type syncbaseHandler struct{ *handler }

func internalServerError(w http.ResponseWriter, doing string, err error) {
	w.WriteHeader(http.StatusInternalServerError)
	fmt.Fprintf(w, "Problem %s: %v", doing, err)
}

func badRequest(w http.ResponseWriter, problem string) {
	w.WriteHeader(http.StatusBadRequest)
	fmt.Fprintf(w, problem)
}

func (h *syncbaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server = r.FormValue("n")
		fakeIt = len(r.FormValue("fake")) > 0 // for testing
	)
	ctx, tracer := newTracer(h.ctx)
	if len(server) == 0 {
		badRequest(w, "Must specify a server with the URL query parameter 'n'")
		return
	}

	service, hasSyncbase, err := syncbaseService(ctx, server, fakeIt)
	if err != nil {
		internalServerError(w, "getting interfaces", err)
		return
	}

	if !hasSyncbase {
		args := struct {
			ServerName  string
			CommandLine string
			Vtrace      *Tracer
		}{
			ServerName:  server,
			CommandLine: "(no command line)",
			Vtrace:      tracer,
		}
		h.execute(h.ctx, w, r, noSyncbaseTmpl, args)
		return
	}

	dbIds, err := service.ListDatabases(ctx)
	if err != nil {
		internalServerError(w, "listing databases", err)
		return
	}
	sbTree := sbtree.AssembleSyncbaseTree(ctx, server, service, dbIds)

	args := struct {
		ServerName  string
		CommandLine string
		Vtrace      *Tracer
		Tree        *sbtree.SyncbaseTree
	}{
		ServerName:  server,
		CommandLine: fmt.Sprintf(`debug glob "%s/*"`, server),
		Vtrace:      tracer,
		Tree:        sbTree,
	}
	h.execute(h.ctx, w, r, syncbaseTmpl, args)
}

func syncbaseService(ctx *context.T, server string, fakeIt bool) (service syncbase.Service, hasSyncbase bool, err error) {
	if fakeIt {
		service = fake.Service(
			errors.New("pretend we cannot list collections"),
			errors.New("pretend we cannot get syncgroup spec"),
		)
		hasSyncbase = true
		return
	}
	hasSyncbase, err = hasSyncbaseService(ctx, server)
	if err != nil {
		return
	}
	if hasSyncbase {
		service = syncbase.NewService(server)
	}
	return
}

// hasSyncbaseService determines whether the given server implements the
// Syncbase interface.
func hasSyncbaseService(ctx *context.T, server string) (bool, error) {
	const (
		syncbasePkgPath = "v.io/v23/services/syncbase"
		syncbaseName    = "Service"
	)
	interfaces, err := reserved.Signature(ctx, server)
	if err != nil {
		return false, err
	}
	for _, ifc := range interfaces {
		if ifc.Name == syncbaseName && ifc.PkgPath == syncbasePkgPath {
			return true, nil
		}
	}
	return false, nil
}

// collectionHandler handles the Collections details page that is linked off the
// main Syncbase viewer page.
type collectionHandler struct{ *handler }

const keysPerPage = 7

func (h *collectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var (
		server       = r.FormValue("n")
		dbBlessing   = r.FormValue("db")
		dbName       = r.FormValue("dn")
		collBlessing = r.FormValue("cb")
		collName     = r.FormValue("cn")
		firstKey     = r.FormValue("firstkey")
	)
	ctx, tracer := newTracer(h.ctx)
	if len(server) == 0 {
		badRequest(w, "Must specify a server with the URL query parameter 'n'")
		return
	}

	collTree := sbtree.AssembleCollectionTree(
		ctx, server,
		dbBlessing, dbName,
		collBlessing, collName,
		firstKey, keysPerPage)

	// Assemble data and send it to the template to generate HTML
	args := struct {
		ServerName  string
		CommandLine string
		Vtrace      *Tracer
		Tree        *sbtree.CollectionTree
	}{
		ServerName:  server,
		CommandLine: "(no command line)",
		Vtrace:      tracer,
		Tree:        collTree,
	}
	h.execute(h.ctx, w, r, collectionTmpl, args)
}

func writeEvent(w http.ResponseWriter, data string) {
	fmt.Fprintf(w, "data: %s\n\n", strings.TrimSpace(data))
}

func writeErrorEvent(w http.ResponseWriter, err error) {
	id := fmt.Sprintf("%v", verror.ErrorID(err))
	writeEvent(w, fmt.Sprintf("ERROR(%v): %v", html.EscapeString(id), html.EscapeString(err.Error())))
}

// Tracer forces collection of a trace rooted at the call to newTracer.
type Tracer struct {
	ctx  *context.T
	span vtrace.Span
}

func newTracer(ctx *context.T) (*context.T, *Tracer) {
	ctx, span := vtrace.WithNewTrace(ctx)
	vtrace.ForceCollect(ctx, 0)
	return ctx, &Tracer{ctx, span}
}

func (t *Tracer) String() string {
	if t == nil {
		return ""
	}
	tr := vtrace.GetStore(t.ctx).TraceRecord(t.span.Trace())
	if len(tr.Spans) == 0 {
		// Do not bother with empty traces
		return ""
	}
	var buf bytes.Buffer
	// nil as the time.Location is fine because the HTTP "server" time is
	// the same as that of the "client" (typically a browser on localhost).
	vtrace.FormatTrace(&buf, vtrace.GetStore(t.ctx).TraceRecord(t.span.Trace()), nil)
	return buf.String()
}
