// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Package subcmd provides a multi-command interface for command line tools.
package subcmd

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"net/http"
	"net/http/pprof"
	"os"
	"path/filepath"
	"strings"
	"text/tabwriter"
)

// ErrInvalidCLA is the error returned when an invalid command line argument was
// provided, and the usage was already printed.
var ErrInvalidCLA = errors.New("invalid command line args")

// InvalidCLA shows the flag usage, and returns ErrInvalidCLA
func InvalidCLA() error {
	flag.Usage()
	return ErrInvalidCLA
}

// Command is the interface for a command
// Data is a generic data type passed down to the sub-command when run.
type Command[Data any] interface {
	// Name returns the name of the command.
	Name() string
	// Desc returns a description of the command.
	Desc() string
	// RegisterFlags registers all the command-specific flags
	// Returns a list of mandatory arguments that must immediately follow the
	// command name
	RegisterFlags(context.Context, Data) ([]string, error)
	// Run invokes the command
	Run(context.Context, Data) error
}

// Run handles the parses the command line arguments, possibly invoking one of
// the provided commands.
// If the command line arguments are invalid, then an error message is printed
// and Run returns ErrInvalidCLA.
func Run[Data any](ctx context.Context, data Data, cmds ...Command[Data]) error {
	_, exe := filepath.Split(os.Args[0])

	flag.Usage = func() {
		out := flag.CommandLine.Output()
		tw := tabwriter.NewWriter(out, 0, 1, 0, ' ', 0)
		fmt.Fprintln(tw, exe, "[command]")
		fmt.Fprintln(tw)
		fmt.Fprintln(tw, "Commands:")
		for _, cmd := range cmds {
			fmt.Fprintln(tw, "  ", cmd.Name(), "\t-", cmd.Desc())
		}
		fmt.Fprintln(tw)
		fmt.Fprintln(tw, "Common flags:")
		tw.Flush()
		flag.PrintDefaults()
	}

	profile := false
	flag.BoolVar(&profile, "profile", false, "enable a webserver at localhost:8080/profile that exposes a CPU profiler")
	mux := http.NewServeMux()
	mux.HandleFunc("/profile", pprof.Profile)

	if len(os.Args) < 2 {
		return InvalidCLA()
	}
	help := os.Args[1] == "help"
	if help {
		copy(os.Args[1:], os.Args[2:])
		os.Args = os.Args[:len(os.Args)-1]
	}

	for _, cmd := range cmds {
		if cmd.Name() == os.Args[1] {
			out := flag.CommandLine.Output()
			mandatory, err := cmd.RegisterFlags(ctx, data)
			if err != nil {
				return err
			}
			flag.Usage = func() {
				flagsAndArgs := append([]string{"<flags>"}, mandatory...)
				fmt.Fprintln(out, exe, cmd.Name(), strings.Join(flagsAndArgs, " "))
				fmt.Fprintln(out)
				fmt.Fprintln(out, cmd.Desc())
				fmt.Fprintln(out)
				fmt.Fprintln(out, "flags:")
				flag.PrintDefaults()
			}
			if help {
				flag.Usage()
				return nil
			}
			args := os.Args[2:] // all arguments after the exe and command
			if err := flag.CommandLine.Parse(args); err != nil {
				return err
			}
			if nonFlagArgs := flag.Args(); len(nonFlagArgs) < len(mandatory) {
				fmt.Fprintln(out, "missing argument", mandatory[len(nonFlagArgs)])
				fmt.Fprintln(out)
				return InvalidCLA()
			}
			if profile {
				fmt.Println("download profile at: localhost:8080/profile")
				fmt.Println("then run: 'go tool pprof <file>'")
				go http.ListenAndServe(":8080", mux)
			}
			return cmd.Run(ctx, data)
		}
	}

	return InvalidCLA()
}
