// Copyright 2019 The Fuchsia 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 main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/golang/glog"
)

const defaultCategories = "app,benchmark,gfx,input,kernel:meta,kernel:sched,ledger,magma,modular,motown,view,flutter,dart,dart:compiler,dart:dart,dart:debugger,dart:embedder,dart:gc,dart:isolate,dart:profiler,dart:vm"

type captureTraceConfig struct {
	Categories           string
	BufferSize           uint // [MB]
	BufferingMode        string
	Duration             time.Duration
	// Command is set differently as it is passed via positional args.
	Command              []string
	BenchmarkResultsFile string
	SpecFile             string
	Binary               bool
	Stream               bool
	Compress             bool
	Detach               bool
	Decouple             bool
	Spawn                bool
}

func newCaptureTraceConfig(f *flag.FlagSet) *captureTraceConfig {
	config := &captureTraceConfig{}

	// TODO(TO-400): It would be nice to be able to specify +category or
	// -category to add or subtract from the default set.
	f.StringVar(&config.Categories, "categories", defaultCategories,
		"Comma separated list of categories to trace. \"all\" for all categories.")
	f.UintVar(&config.BufferSize, "buffer-size", 0,
		"Size of trace buffer in MB.")
	f.StringVar(&config.BufferingMode, "buffering-mode", "oneshot",
		"Buffering mode (one of: oneshot,circular,streaming.")
	f.DurationVar(&config.Duration, "duration", 0,
		"Duration of trace capture (e.g. '10s').  Second resolution.")
	f.StringVar(&config.SpecFile, "spec-file", "",
		"Tracing specification file.")
	f.StringVar(
		&config.BenchmarkResultsFile,
		"benchmark-results-file",
		"",
		"Relative filepath for storing benchmark results.",
	)
	f.BoolVar(&config.Binary, "binary", false,
		"Capture trace in binary format on the target.")
	f.BoolVar(&config.Stream, "stream", false,
		"Stream trace output to a local file, instead of saving to target disk and then copying it.")
	// TODO(PT-125): Update this message when compressed binary (fxt) traces are supported.
	f.BoolVar(&config.Compress, "compress", false,
		"Compress the trace output before writing to disk. This option is currently ignored if -stream or -binary is specified.")
	f.BoolVar(&config.Detach, "detach", false,
		"Don't stop the traced program when tracing finished.")
	f.BoolVar(&config.Decouple, "decouple", false,
		"Don't stop tracing when the traced program exits.")
	f.BoolVar(&config.Spawn, "spawn", false,
		"Use fdio_spawn to run a legacy app. Detach will have no effect when using this option.")

	return config
}

func streamTraceOutput(listener net.Listener, traceOutput *os.File, streamStatus chan<- error) {
	fmt.Printf("Listening for remote connection: %s\n", listener.Addr().(*net.TCPAddr).String())
	conn, err := listener.Accept()
	if err != nil {
		streamStatus <- fmt.Errorf("Unable to accept incoming trace connection: %s", err.Error())
		return
	}
	fmt.Printf("Incoming trace stream connected\n")
	nBytes, err := io.Copy(traceOutput, conn)
	conn.Close()
	if err != nil {
		streamStatus <- fmt.Errorf("Error writing trace results: %s", err.Error())
	} else {
		fmt.Printf("Wrote trace output, %d bytes\n", nBytes)
		streamStatus <- nil
	}
}

func captureTrace(config *captureTraceConfig, conn *TargetConnection, traceOutput *os.File) error {
	cmd := []string{"trace"}
	// Pass on our verbosity level to trace.
	if glog.V(2) {
		cmd = append(cmd, "--verbose=2")
	} else if glog.V(1) {
		cmd = append(cmd, "--verbose=1")
	}
	cmd = append(cmd, "record")

	if config.Categories == "" {
		config.Categories = defaultCategories
	}

	if len(config.SpecFile) > 0 {
		cmd = append(cmd, "--spec-file="+config.SpecFile)
	}

	if len(config.BenchmarkResultsFile) > 0 {
		cmd = append(cmd, "--benchmark-results-file="+config.BenchmarkResultsFile)
	}

	if config.Categories != "all" {
		cmd = append(cmd, "--categories="+config.Categories)
	}

	if config.BufferSize != 0 {
		cmd = append(cmd, "--buffer-size="+
			strconv.FormatUint(uint64(config.BufferSize), 10))
	}
	if config.BufferingMode == "oneshot" ||
		config.BufferingMode == "circular" ||
		config.BufferingMode == "streaming" {
		cmd = append(cmd, "--buffering-mode="+config.BufferingMode)
	} else {
		return fmt.Errorf("Invalid value for --buffering-mode: %s",
			config.BufferingMode)
	}
	if config.Duration != 0 {
		cmd = append(cmd, "--duration="+
			strconv.FormatUint(uint64(config.Duration.Seconds()), 10))
	}
	if config.Binary {
		cmd = append(cmd, "--binary")
	}
	if config.Compress {
		cmd = append(cmd, "--compress")
	}

	var listener net.Listener
	var err error
	streamChan := make(chan error)
	if config.Stream {
		listener, err = conn.client.ListenTCP(&net.TCPAddr{IP: net.IPv6loopback})
		if err != nil {
			return err
		}
		cmd = append(cmd, "--output-file=tcp:"+listener.Addr().(*net.TCPAddr).String())
		defer func() {
			if listener != nil {
				glog.Info("Closing trace stream listener")
				listener.Close()
			}
		}()
		go streamTraceOutput(listener, traceOutput, streamChan)
	}

	if config.Detach {
		cmd = append(cmd, "--detach")
	}
	if config.Decouple {
		cmd = append(cmd, "--decouple")
	}
	if config.Spawn {
		cmd = append(cmd, "--spawn")
	}

	// The program to run must appear last.
	// TODO(PT-130): The handling of embedded spaces in the command
	// and its arguments could be better.
	if len(config.Command) > 0 {
		// There is a difference between the trace failing and the
		// child failing, we need to know if trace fails.
		// TODO(PT-95): If we talk to trace-manager directly to get
		// trace data and then talk to some other service to launch the
		// child then there's no conflating of return codes.
		cmd = append(cmd, "--return-child-result=false")
		cmd = append(cmd, config.Command...)
	}

	// TODO(TO-401): The target `trace` command's output is misleading.
	// Specifically it says "Trace file written to /tmp/trace.json" which
	// references where the file is written to on the target not on the host.
	// We should wrap this and offer less confusing status.
	err = conn.RunCommand(strings.Join(cmd, " "))
	if err != nil {
		return err
	}

	// Check for an error during streaming.
	if config.Stream {
		fmt.Printf("Waiting to finish receiving trace stream ...\n")
		err = <-streamChan
	}

	return err
}

func convertToHtml(generator string, outputPath string,
	title string, inputPaths ...string) error {
	fmt.Printf("Converting %v to %s... ", inputPaths, outputPath)
	var args []string
	args = append(args, "--output="+outputPath)
	if title != "" {
		args = append(args, "--title="+title)
	}
	args = append(args, inputPaths...)
	err := runCommand(generator, args)
	if err != nil {
		fmt.Printf("failed: %s\n", err.Error())
		fmt.Printf("Invoked as: %s %s\n", generator, args)
	} else {
		fmt.Println("done.")
	}
	return err
}

func convertToJson(generator string, outputPath string, inputPath string) error {
	fmt.Printf("Converting %s to %s... ", inputPath, outputPath)
	var args []string
	args = append(args, "--input-file="+inputPath)
	args = append(args, "--output-file="+outputPath)
	err := runCommand(generator, args)
	if err != nil {
		fmt.Printf("failed: %s\n", err.Error())
		fmt.Printf("Invoked as: %s %s\n", generator, args)
	} else {
		fmt.Println("done.")
	}
	return err
}
