// Copyright 2020 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 fuzz

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/golang/glog"
)

// API version
const (
	VersionMajor = 0
	VersionMinor = 1
	VersionPatch = 0
)

// Available subcommand names
const (
	StartInstance = "start_instance"
	StopInstance  = "stop_instance"
	ListFuzzers   = "list_fuzzers"
	PrepareFuzzer = "prepare_fuzzer"
	GetLogs       = "get_logs"
	RunFuzzer     = "run_fuzzer"
	GetData       = "get_data"
	PutData       = "put_data"
	Version       = "version"
)

var commandDesc = map[string]string{
	StartInstance: "Start a Fuchsia instance",
	StopInstance:  "Stop a Fuchsia instance",
	ListFuzzers:   "List available fuzz targets on an instance",
	PrepareFuzzer: "Prepare a fuzzer to be run",
	GetLogs:       "Get debug logs from an instance",
	RunFuzzer:     "Run a fuzz target on an instance (passing any extra args to libFuzzer)",
	GetData:       "Copy files between an instance and a local path",
	PutData:       "Copy files between a local path and an instance",
	Version:       "Get API version",
}

// An APICommand is the structured result of parsing the command-line args
type APICommand struct {
	name string

	handle  string
	fuzzer  string
	srcPath string
	dstPath string

	extraArgs []string
}

// Execute the APICommand, writing any output to the given io.Writer
func (c *APICommand) Execute(out io.Writer) error {
	var instance Instance

	glog.Infof("Running API command: %v\n", c)

	// For commands that take a handle, load the Instance from the handle
	if c.handle != "" {
		handle, err := LoadHandleFromString(c.handle)
		if err != nil {
			return fmt.Errorf("Bad handle: %s", err)
		}

		// stop_instance should make its best effort even with an incomplete
		// handle, as long as it contains enough information
		verify := c.name != StopInstance
		if instance, err = loadInstanceFromHandle(handle, verify); err != nil {
			return fmt.Errorf("Bad handle: %s", err)
		}
		defer instance.Close()
	}

	switch c.name {
	case StartInstance:
		instance, err := NewInstance()
		if err != nil {
			return fmt.Errorf("Error creating instance: %s", err)
		}

		glog.Info("Starting instance...")
		if err := instance.Start(); err != nil {
			return fmt.Errorf("Error starting instance: %s", err)
		}
		glog.Info("Instance started.")
		defer instance.Close()

		handle, err := instance.Handle()
		if err != nil {
			return fmt.Errorf("Error getting instance handle: %s", err)
		}
		fmt.Fprintf(out, "%s\n", handle.Serialize())
	case StopInstance:
		return instance.Stop()
	case ListFuzzers:
		for _, name := range instance.ListFuzzers() {
			fmt.Fprintf(out, "%s\n", name)
		}
	case PrepareFuzzer:
		return instance.PrepareFuzzer(c.fuzzer)
	case GetLogs:
		return instance.GetLogs(out)
	case GetData:
		return instance.Get(c.fuzzer, c.srcPath, c.dstPath)
	case PutData:
		return instance.Put(c.fuzzer, c.srcPath, c.dstPath)
	case RunFuzzer:
		// TODO(fxbug.dev/45431): buffer output so we don't get prematurely terminated by CF
		return instance.RunFuzzer(out, c.fuzzer, c.dstPath, c.extraArgs...)
	case Version:
		fmt.Fprintf(out, "v%d.%d.%d\n", VersionMajor, VersionMinor, VersionPatch)
	}
	return nil
}

// ParseArgs converts command-line args into an API-command
func ParseArgs(args []string) (*APICommand, error) {
	if len(args) == 0 {
		printUsage()
		return nil, fmt.Errorf("missing subcommand")
	}

	cmd := &APICommand{name: args[0]}

	flagSet := flag.NewFlagSet(cmd.name, flag.ContinueOnError)
	handleDesc := fmt.Sprintf("an instance `handle`, as returned by %s", StartInstance)
	fuzzerDesc := fmt.Sprintf("a `fuzzer` name, as returned by %s", ListFuzzers)

	var requiredArgs []*string

	switch cmd.name {
	case StartInstance, Version:
	case StopInstance, ListFuzzers, GetLogs:
		flagSet.StringVar(&cmd.handle, "handle", "", handleDesc)
		requiredArgs = []*string{&cmd.handle}
	case PrepareFuzzer:
		flagSet.StringVar(&cmd.handle, "handle", "", handleDesc)
		flagSet.StringVar(&cmd.fuzzer, "fuzzer", "", fuzzerDesc)
		requiredArgs = []*string{&cmd.handle, &cmd.fuzzer}
	case RunFuzzer:
		flagSet.StringVar(&cmd.handle, "handle", "", handleDesc)
		flagSet.StringVar(&cmd.fuzzer, "fuzzer", "", fuzzerDesc)
		flagSet.StringVar(&cmd.dstPath, "artifact-dir", "", "host `path` to store artifacts")
		requiredArgs = []*string{&cmd.handle, &cmd.fuzzer}
	case GetData:
		flagSet.StringVar(&cmd.handle, "handle", "", handleDesc)
		flagSet.StringVar(&cmd.fuzzer, "fuzzer", "", fuzzerDesc)
		flagSet.StringVar(&cmd.srcPath, "src", "", "target source `path` (may include glob)")
		flagSet.StringVar(&cmd.dstPath, "dst", "", "host destination `path`")
		requiredArgs = []*string{&cmd.handle, &cmd.fuzzer, &cmd.srcPath, &cmd.dstPath}
	case PutData:
		flagSet.StringVar(&cmd.handle, "handle", "", handleDesc)
		flagSet.StringVar(&cmd.fuzzer, "fuzzer", "", fuzzerDesc)
		flagSet.StringVar(&cmd.srcPath, "src", "", "host source `path` (may include glob)")
		flagSet.StringVar(&cmd.dstPath, "dst", "", "target destination `path`")
		requiredArgs = []*string{&cmd.handle, &cmd.fuzzer, &cmd.srcPath, &cmd.dstPath}
	default:
		printUsage()
		return nil, fmt.Errorf("unknown subcommand: %s", cmd.name)
	}

	if err := flagSet.Parse(args[1:]); err != nil {
		// Usage will already have been printed by Parse() in this case
		return nil, err
	}

	// Handle missing arguments
	for _, arg := range requiredArgs {
		if *arg == "" {
			flagSet.Usage()
			return nil, fmt.Errorf("not enough arguments")
		}
	}

	// Handle any extra args
	if flagSet.NArg() > 0 {
		if cmd.name == RunFuzzer {
			cmd.extraArgs = flagSet.Args()
		} else {
			flagSet.Usage()
			return nil, fmt.Errorf("too many arguments")
		}
	}

	return cmd, nil
}

func printUsage() {
	fmt.Printf("Usage: %s <subcommand>\n\n", os.Args[0])
	fmt.Printf("Supported subcommands:\n")
	for name, desc := range commandDesc {
		fmt.Printf(" - %s: %s\n", name, desc)
	}
}
