// 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 commands defines and manages the basic pprof commands
package commands

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
	"strings"

	"cmd/pprof/internal/plugin"
	"cmd/pprof/internal/report"
	"cmd/pprof/internal/svg"
	"cmd/pprof/internal/tempfile"
)

// Commands describes the commands accepted by pprof.
type Commands map[string]*Command

// Command describes the actions for a pprof command. Includes a
// function for command-line completion, the report format to use
// during report generation, any postprocessing functions, and whether
// the command expects a regexp parameter (typically a function name).
type Command struct {
	Complete    Completer     // autocomplete for interactive mode
	Format      int           // report format to generate
	PostProcess PostProcessor // postprocessing to run on report
	HasParam    bool          // Collect a parameter from the CLI
	Usage       string        // Help text
}

// Completer is a function for command-line autocompletion
type Completer func(prefix string) string

// PostProcessor is a function that applies post-processing to the report output
type PostProcessor func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error

// PProf returns the basic pprof report-generation commands
func PProf(c Completer, interactive **bool, svgpan **string) Commands {
	return Commands{
		// Commands that require no post-processing.
		"tags":   {nil, report.Tags, nil, false, "Outputs all tags in the profile"},
		"raw":    {c, report.Raw, nil, false, "Outputs a text representation of the raw profile"},
		"dot":    {c, report.Dot, nil, false, "Outputs a graph in DOT format"},
		"top":    {c, report.Text, nil, false, "Outputs top entries in text form"},
		"tree":   {c, report.Tree, nil, false, "Outputs a text rendering of call graph"},
		"text":   {c, report.Text, nil, false, "Outputs top entries in text form"},
		"disasm": {c, report.Dis, nil, true, "Output annotated assembly for functions matching regexp or address"},
		"list":   {c, report.List, nil, true, "Output annotated source for functions matching regexp"},
		"peek":   {c, report.Tree, nil, true, "Output callers/callees of functions matching regexp"},

		// Save binary formats to a file
		"callgrind": {c, report.Callgrind, awayFromTTY("callgraph.out"), false, "Outputs a graph in callgrind format"},
		"proto":     {c, report.Proto, awayFromTTY("pb.gz"), false, "Outputs the profile in compressed protobuf format"},

		// Generate report in DOT format and postprocess with dot
		"gif": {c, report.Dot, invokeDot("gif"), false, "Outputs a graph image in GIF format"},
		"pdf": {c, report.Dot, invokeDot("pdf"), false, "Outputs a graph in PDF format"},
		"png": {c, report.Dot, invokeDot("png"), false, "Outputs a graph image in PNG format"},
		"ps":  {c, report.Dot, invokeDot("ps"), false, "Outputs a graph in PS format"},

		// Save SVG output into a file after including svgpan library
		"svg": {c, report.Dot, saveSVGToFile(svgpan), false, "Outputs a graph in SVG format"},

		// Visualize postprocessed dot output
		"eog":    {c, report.Dot, invokeVisualizer(interactive, invokeDot("svg"), "svg", []string{"eog"}), false, "Visualize graph through eog"},
		"evince": {c, report.Dot, invokeVisualizer(interactive, invokeDot("pdf"), "pdf", []string{"evince"}), false, "Visualize graph through evince"},
		"gv":     {c, report.Dot, invokeVisualizer(interactive, invokeDot("ps"), "ps", []string{"gv --noantialias"}), false, "Visualize graph through gv"},
		"web":    {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers()), false, "Visualize graph through web browser"},

		// Visualize HTML directly generated by report.
		"weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers()), true, "Output annotated source in HTML for functions matching regexp or address"},
	}
}

// browsers returns a list of commands to attempt for web visualization
// on the current platform
func browsers() []string {
	cmds := []string{"chrome", "google-chrome", "firefox"}
	switch runtime.GOOS {
	case "darwin":
		cmds = append(cmds, "/usr/bin/open")
	case "windows":
		cmds = append(cmds, "cmd /c start")
	default:
		cmds = append(cmds, "xdg-open")
	}
	return cmds
}

// NewCompleter creates an autocompletion function for a set of commands.
func NewCompleter(cs Commands) Completer {
	return func(line string) string {
		switch tokens := strings.Fields(line); len(tokens) {
		case 0:
			// Nothing to complete
		case 1:
			// Single token -- complete command name
			found := ""
			for c := range cs {
				if strings.HasPrefix(c, tokens[0]) {
					if found != "" {
						return line
					}
					found = c
				}
			}
			if found != "" {
				return found
			}
		default:
			// Multiple tokens -- complete using command completer
			if c, ok := cs[tokens[0]]; ok {
				if c.Complete != nil {
					lastTokenIdx := len(tokens) - 1
					lastToken := tokens[lastTokenIdx]
					if strings.HasPrefix(lastToken, "-") {
						lastToken = "-" + c.Complete(lastToken[1:])
					} else {
						lastToken = c.Complete(lastToken)
					}
					return strings.Join(append(tokens[:lastTokenIdx], lastToken), " ")
				}
			}
		}
		return line
	}
}

// awayFromTTY saves the output in a file if it would otherwise go to
// the terminal screen. This is used to avoid dumping binary data on
// the screen.
func awayFromTTY(format string) PostProcessor {
	return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
		if output == os.Stdout && ui.IsTerminal() {
			tempFile, err := tempfile.New("", "profile", "."+format)
			if err != nil {
				return err
			}
			ui.PrintErr("Generating report in ", tempFile.Name())
			_, err = fmt.Fprint(tempFile, input)
			return err
		}
		_, err := fmt.Fprint(output, input)
		return err
	}
}

func invokeDot(format string) PostProcessor {
	divert := awayFromTTY(format)
	return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
		if _, err := exec.LookPath("dot"); err != nil {
			ui.PrintErr("Cannot find dot, have you installed Graphviz?")
			return err
		}
		cmd := exec.Command("dot", "-T"+format)
		var buf bytes.Buffer
		cmd.Stdin, cmd.Stdout, cmd.Stderr = input, &buf, os.Stderr
		if err := cmd.Run(); err != nil {
			return err
		}
		return divert(&buf, output, ui)
	}
}

func saveSVGToFile(svgpan **string) PostProcessor {
	generateSVG := invokeDot("svg")
	divert := awayFromTTY("svg")
	return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
		baseSVG := &bytes.Buffer{}
		generateSVG(input, baseSVG, ui)
		massaged := &bytes.Buffer{}
		fmt.Fprint(massaged, svg.Massage(*baseSVG, **svgpan))
		return divert(massaged, output, ui)
	}
}

func invokeVisualizer(interactive **bool, format PostProcessor, suffix string, visualizers []string) PostProcessor {
	return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
		tempFile, err := tempfile.New(os.Getenv("PPROF_TMPDIR"), "pprof", "."+suffix)
		if err != nil {
			return err
		}
		tempfile.DeferDelete(tempFile.Name())
		if err = format(input, tempFile, ui); err != nil {
			return err
		}
		tempFile.Close() // on windows, if the file is Open, start cannot access it.
		// Try visualizers until one is successful
		for _, v := range visualizers {
			// Separate command and arguments for exec.Command.
			args := strings.Split(v, " ")
			if len(args) == 0 {
				continue
			}
			viewer := exec.Command(args[0], append(args[1:], tempFile.Name())...)
			viewer.Stderr = os.Stderr
			if err = viewer.Start(); err == nil {
				if !**interactive {
					// In command-line mode, wait for the viewer to be closed
					// before proceeding
					return viewer.Wait()
				}
				return nil
			}
		}
		return err
	}
}
