// Copyright 2014 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 report

// This file contains routines related to the generation of annotated
// source listings.

import (
	"bufio"
	"fmt"
	"html/template"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"cmd/internal/pprof/plugin"
)

// printSource prints an annotated source listing, include all
// functions with samples that match the regexp rpt.options.symbol.
// The sources are sorted by function name and then by filename to
// eliminate potential nondeterminism.
func printSource(w io.Writer, rpt *Report) error {
	o := rpt.options
	g, err := newGraph(rpt)
	if err != nil {
		return err
	}

	// Identify all the functions that match the regexp provided.
	// Group nodes for each matching function.
	var functions nodes
	functionNodes := make(map[string]nodes)
	for _, n := range g.ns {
		if !o.Symbol.MatchString(n.info.name) {
			continue
		}
		if functionNodes[n.info.name] == nil {
			functions = append(functions, n)
		}
		functionNodes[n.info.name] = append(functionNodes[n.info.name], n)
	}
	functions.sort(nameOrder)

	fmt.Fprintf(w, "Total: %s\n", rpt.formatValue(rpt.total))
	for _, fn := range functions {
		name := fn.info.name

		// Identify all the source files associated to this function.
		// Group nodes for each source file.
		var sourceFiles nodes
		fileNodes := make(map[string]nodes)
		for _, n := range functionNodes[name] {
			if n.info.file == "" {
				continue
			}
			if fileNodes[n.info.file] == nil {
				sourceFiles = append(sourceFiles, n)
			}
			fileNodes[n.info.file] = append(fileNodes[n.info.file], n)
		}

		if len(sourceFiles) == 0 {
			fmt.Printf("No source information for %s\n", name)
			continue
		}

		sourceFiles.sort(fileOrder)

		// Print each file associated with this function.
		for _, fl := range sourceFiles {
			filename := fl.info.file
			fns := fileNodes[filename]
			flatSum, cumSum := sumNodes(fns)

			fnodes, path, err := getFunctionSource(name, filename, fns, 0, 0)
			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
				percentage(cumSum, rpt.total))

			if err != nil {
				fmt.Fprintf(w, " Error: %v\n", err)
				continue
			}

			for _, fn := range fnodes {
				fmt.Fprintf(w, "%10s %10s %6d:%s\n", valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt), fn.info.lineno, fn.info.name)
			}
		}
	}
	return nil
}

// printWebSource prints an annotated source listing, include all
// functions with samples that match the regexp rpt.options.symbol.
func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
	o := rpt.options
	g, err := newGraph(rpt)
	if err != nil {
		return err
	}

	// If the regexp source can be parsed as an address, also match
	// functions that land on that address.
	var address *uint64
	if hex, err := strconv.ParseUint(o.Symbol.String(), 0, 64); err == nil {
		address = &hex
	}

	// Extract interesting symbols from binary files in the profile and
	// classify samples per symbol.
	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
	symNodes := nodesPerSymbol(g.ns, symbols)

	// Sort symbols for printing.
	var syms objSymbols
	for s := range symNodes {
		syms = append(syms, s)
	}
	sort.Sort(syms)

	if len(syms) == 0 {
		return fmt.Errorf("no samples found on routines matching: %s", o.Symbol.String())
	}

	printHeader(w, rpt)
	for _, s := range syms {
		name := s.sym.Name[0]
		// Identify sources associated to a symbol by examining
		// symbol samples. Classify samples per source file.
		var sourceFiles nodes
		fileNodes := make(map[string]nodes)
		for _, n := range symNodes[s] {
			if n.info.file == "" {
				continue
			}
			if fileNodes[n.info.file] == nil {
				sourceFiles = append(sourceFiles, n)
			}
			fileNodes[n.info.file] = append(fileNodes[n.info.file], n)
		}

		if len(sourceFiles) == 0 {
			fmt.Printf("No source information for %s\n", name)
			continue
		}

		sourceFiles.sort(fileOrder)

		// Print each file associated with this function.
		for _, fl := range sourceFiles {
			filename := fl.info.file
			fns := fileNodes[filename]

			asm := assemblyPerSourceLine(symbols, fns, filename, obj)
			start, end := sourceCoordinates(asm)

			fnodes, path, err := getFunctionSource(name, filename, fns, start, end)
			if err != nil {
				fnodes, path = getMissingFunctionSource(filename, asm, start, end)
			}

			flatSum, cumSum := sumNodes(fnodes)
			printFunctionHeader(w, name, path, flatSum, cumSum, rpt)
			for _, fn := range fnodes {
				printFunctionSourceLine(w, fn, asm[fn.info.lineno], rpt)
			}
			printFunctionClosing(w)
		}
	}
	printPageClosing(w)
	return nil
}

// sourceCoordinates returns the lowest and highest line numbers from
// a set of assembly statements.
func sourceCoordinates(asm map[int]nodes) (start, end int) {
	for l := range asm {
		if start == 0 || l < start {
			start = l
		}
		if end == 0 || l > end {
			end = l
		}
	}
	return start, end
}

// assemblyPerSourceLine disassembles the binary containing a symbol
// and classifies the assembly instructions according to its
// corresponding source line, annotating them with a set of samples.
func assemblyPerSourceLine(objSyms []*objSymbol, rs nodes, src string, obj plugin.ObjTool) map[int]nodes {
	assembly := make(map[int]nodes)
	// Identify symbol to use for this collection of samples.
	o := findMatchingSymbol(objSyms, rs)
	if o == nil {
		return assembly
	}

	// Extract assembly for matched symbol
	insns, err := obj.Disasm(o.sym.File, o.sym.Start, o.sym.End)
	if err != nil {
		return assembly
	}

	srcBase := filepath.Base(src)
	anodes := annotateAssembly(insns, rs, o.base)
	var lineno = 0
	for _, an := range anodes {
		if filepath.Base(an.info.file) == srcBase {
			lineno = an.info.lineno
		}
		if lineno != 0 {
			assembly[lineno] = append(assembly[lineno], an)
		}
	}

	return assembly
}

// findMatchingSymbol looks for the symbol that corresponds to a set
// of samples, by comparing their addresses.
func findMatchingSymbol(objSyms []*objSymbol, ns nodes) *objSymbol {
	for _, n := range ns {
		for _, o := range objSyms {
			if filepath.Base(o.sym.File) == n.info.objfile &&
				o.sym.Start <= n.info.address-o.base &&
				n.info.address-o.base <= o.sym.End {
				return o
			}
		}
	}
	return nil
}

// printHeader prints the page header for a weblist report.
func printHeader(w io.Writer, rpt *Report) {
	fmt.Fprintln(w, weblistPageHeader)

	var labels []string
	for _, l := range legendLabels(rpt) {
		labels = append(labels, template.HTMLEscapeString(l))
	}

	fmt.Fprintf(w, `<div class="legend">%s<br>Total: %s</div>`,
		strings.Join(labels, "<br>\n"),
		rpt.formatValue(rpt.total),
	)
}

// printFunctionHeader prints a function header for a weblist report.
func printFunctionHeader(w io.Writer, name, path string, flatSum, cumSum int64, rpt *Report) {
	fmt.Fprintf(w, `<h1>%s</h1>%s
<pre onClick="pprof_toggle_asm(event)">
  Total:  %10s %10s (flat, cum) %s
`,
		template.HTMLEscapeString(name), template.HTMLEscapeString(path),
		rpt.formatValue(flatSum), rpt.formatValue(cumSum),
		percentage(cumSum, rpt.total))
}

// printFunctionSourceLine prints a source line and the corresponding assembly.
func printFunctionSourceLine(w io.Writer, fn *node, assembly nodes, rpt *Report) {
	if len(assembly) == 0 {
		fmt.Fprintf(w,
			"<span class=line> %6d</span> <span class=nop>  %10s %10s %s </span>\n",
			fn.info.lineno,
			valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt),
			template.HTMLEscapeString(fn.info.name))
		return
	}

	fmt.Fprintf(w,
		"<span class=line> %6d</span> <span class=deadsrc>  %10s %10s %s </span>",
		fn.info.lineno,
		valueOrDot(fn.flat, rpt), valueOrDot(fn.cum, rpt),
		template.HTMLEscapeString(fn.info.name))
	fmt.Fprint(w, "<span class=asm>")
	for _, an := range assembly {
		var fileline string
		class := "disasmloc"
		if an.info.file != "" {
			fileline = fmt.Sprintf("%s:%d", template.HTMLEscapeString(an.info.file), an.info.lineno)
			if an.info.lineno != fn.info.lineno {
				class = "unimportant"
			}
		}
		fmt.Fprintf(w, " %8s %10s %10s %8x: %-48s <span class=%s>%s</span>\n", "",
			valueOrDot(an.flat, rpt), valueOrDot(an.cum, rpt),
			an.info.address,
			template.HTMLEscapeString(an.info.name),
			class,
			template.HTMLEscapeString(fileline))
	}
	fmt.Fprintln(w, "</span>")
}

// printFunctionClosing prints the end of a function in a weblist report.
func printFunctionClosing(w io.Writer) {
	fmt.Fprintln(w, "</pre>")
}

// printPageClosing prints the end of the page in a weblist report.
func printPageClosing(w io.Writer) {
	fmt.Fprintln(w, weblistPageClosing)
}

// getFunctionSource collects the sources of a function from a source
// file and annotates it with the samples in fns. Returns the sources
// as nodes, using the info.name field to hold the source code.
func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, string, error) {
	f, file, err := adjustSourcePath(file)
	if err != nil {
		return nil, file, err
	}

	lineNodes := make(map[int]nodes)

	// Collect source coordinates from profile.
	const margin = 5 // Lines before first/after last sample.
	if start == 0 {
		if fns[0].info.startLine != 0 {
			start = fns[0].info.startLine
		} else {
			start = fns[0].info.lineno - margin
		}
	} else {
		start -= margin
	}
	if end == 0 {
		end = fns[0].info.lineno
	}
	end += margin
	for _, n := range fns {
		lineno := n.info.lineno
		nodeStart := n.info.startLine
		if nodeStart == 0 {
			nodeStart = lineno - margin
		}
		nodeEnd := lineno + margin
		if nodeStart < start {
			start = nodeStart
		} else if nodeEnd > end {
			end = nodeEnd
		}
		lineNodes[lineno] = append(lineNodes[lineno], n)
	}

	var src nodes
	buf := bufio.NewReader(f)
	lineno := 1
	for {
		line, err := buf.ReadString('\n')
		if err != nil {
			if err != io.EOF {
				return nil, file, err
			}
			if line == "" {
				// end was at or past EOF; that's okay
				break
			}
		}
		if lineno >= start {
			flat, cum := sumNodes(lineNodes[lineno])

			src = append(src, &node{
				info: nodeInfo{
					name:   strings.TrimRight(line, "\n"),
					lineno: lineno,
				},
				flat: flat,
				cum:  cum,
			})
		}
		lineno++
		if lineno > end {
			break
		}
	}
	return src, file, nil
}

// getMissingFunctionSource creates a dummy function body to point to
// the source file and annotates it with the samples in asm.
func getMissingFunctionSource(filename string, asm map[int]nodes, start, end int) (nodes, string) {
	var fnodes nodes
	for i := start; i <= end; i++ {
		lrs := asm[i]
		if len(lrs) == 0 {
			continue
		}
		flat, cum := sumNodes(lrs)
		fnodes = append(fnodes, &node{
			info: nodeInfo{
				name:   "???",
				lineno: i,
			},
			flat: flat,
			cum:  cum,
		})
	}
	return fnodes, filename
}

// adjustSourcePath adjusts the path for a source file by trimming
// known prefixes and searching for the file on all parents of the
// current working dir.
func adjustSourcePath(path string) (*os.File, string, error) {
	path = trimPath(path)
	f, err := os.Open(path)
	if err == nil {
		return f, path, nil
	}

	if dir, wderr := os.Getwd(); wderr == nil {
		for {
			parent := filepath.Dir(dir)
			if parent == dir {
				break
			}
			if f, err := os.Open(filepath.Join(parent, path)); err == nil {
				return f, filepath.Join(parent, path), nil
			}

			dir = parent
		}
	}

	return nil, path, err
}

// trimPath cleans up a path by removing prefixes that are commonly
// found on profiles.
func trimPath(path string) string {
	basePaths := []string{
		"/proc/self/cwd/./",
		"/proc/self/cwd/",
	}

	sPath := filepath.ToSlash(path)

	for _, base := range basePaths {
		if strings.HasPrefix(sPath, base) {
			return filepath.FromSlash(sPath[len(base):])
		}
	}
	return path
}
