// Copyright 2015 The Vanadium 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 profilescmdline provides a command line driver
// (for v.io/x/lib/cmdline) for implementing jiri 'profile' subcommands.
// The intent is to support project specific instances of such profiles
// for managing software dependencies.
//
// There are two ways of using the cmdline support, one is to read profile
// information, via RegisterReaderCommands and
// RegisterReaderCommandsUsingParent; the other is to manage profile
// installations via the RegisterManagementCommands function. The management
// commands can manage profiles that are linked into the binary itself
// or invoke external commands that implement the profile management. These
// external 'installer' commands are accessed by specifing them as a prefix
// to the profile name. For example myproject::go will invoke the external
// command jiri-profile-myproject with "go" as the profile name. Thus the
// following invocations are equivalent:
// jiri profile install myproject::go
// jiri profile-myproject install go
//
// Regardless of which is used, the profile name, as seen by profile
// database readers will be myproject::go.
package profilescmdline

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"strings"

	"v.io/jiri"
	"v.io/jiri/profiles"
	"v.io/jiri/profiles/profilesmanager"
	"v.io/x/lib/cmdline"
	"v.io/x/lib/lookpath"
)

// newCmdOSPackages represents the "profile os-packages" command.
func newCmdOSPackages() *cmdline.Command {
	return &cmdline.Command{
		Runner:   jiri.RunnerFunc(runPackages),
		Name:     "os-packages",
		Short:    "List the commands to install the OS packages required by the given profiles",
		Long:     "List or optionally run the commands to install the OS packages required by the given profiles.",
		ArgsName: "<profiles>",
		ArgsLong: "<profiles> is a list of profiles to list OS packages for.",
	}
}

// newCmdInstall represents the "profile install" command.
func newCmdInstall() *cmdline.Command {
	return &cmdline.Command{
		Runner:   jiri.RunnerFunc(runInstall),
		Name:     "install",
		Short:    "Install the given profiles",
		Long:     "Install the given profiles.",
		ArgsName: "<profiles>",
		ArgsLong: "<profiles> is a list of profiles to install.",
	}
}

// newCmdUninstall represents the "profile uninstall" command.
func newCmdUninstall() *cmdline.Command {
	return &cmdline.Command{
		Runner:   jiri.RunnerFunc(runUninstall),
		Name:     "uninstall",
		Short:    "Uninstall the given profiles",
		Long:     "Uninstall the given profiles.",
		ArgsName: "<profiles>",
		ArgsLong: "<profiles> is a list of profiles to uninstall.",
	}
}

// newCmdUpdate represents the "profile update" command.
func newCmdUpdate() *cmdline.Command {
	return &cmdline.Command{
		Runner:   jiri.RunnerFunc(runUpdate),
		Name:     "update",
		Short:    "Install the latest default version of the given profiles",
		Long:     "Install the latest default version of the given profiles.",
		ArgsName: "<profiles>",
		ArgsLong: "<profiles> is a list of profiles to update, if omitted all profiles are updated.",
	}
}

// newCmdCleanup represents the "profile cleanup" command.
func newCmdCleanup() *cmdline.Command {
	return &cmdline.Command{
		Runner:   jiri.RunnerFunc(runCleanup),
		Name:     "cleanup",
		Short:    "Cleanup the locally installed profiles",
		Long:     "Cleanup the locally installed profiles. This is generally required when recovering from earlier bugs or when preparing for a subsequent change to the profiles implementation.",
		ArgsName: "<profiles>",
		ArgsLong: "<profiles> is a list of profiles to cleanup, if omitted all profiles are cleaned.",
	}
}

// newCmdAvailable represents the "profile available" command.
func newCmdAvailable() *cmdline.Command {
	return &cmdline.Command{
		Runner: jiri.RunnerFunc(runAvailable),
		Name:   "available",
		Short:  "List the available profiles",
		Long:   "List the available profiles.",
	}
}

func runUpdate(jirix *jiri.X, args []string) error {
	return updateImpl(jirix, &updateFlags, args)
}

func runCleanup(jirix *jiri.X, args []string) error {
	return cleanupImpl(jirix, &cleanupFlags, args)
}

func runPackages(jirix *jiri.X, args []string) error {
	return packagesImpl(jirix, &packagesFlags, args)
}

func runInstall(jirix *jiri.X, args []string) error {
	return installImpl(jirix, &installFlags, args)
}

func runUninstall(jirix *jiri.X, args []string) error {
	return uninstallImpl(jirix, &uninstallFlags, args)
}

func runAvailable(jirix *jiri.X, args []string) error {
	return availableImpl(jirix, &availableFlags, args)
}

type commonFlagValues struct {
	// The value of --profiles-db
	dbPath string
	// The value of --profiles-dir
	root string
}

func initCommon(flags *flag.FlagSet, c *commonFlagValues, installer, defaultDBPath, defaultProfilesPath string) {
	RegisterDBPathFlag(flags, &c.dbPath, defaultDBPath)
	flags.StringVar(&c.root, "profiles-dir", defaultProfilesPath, "the directory, relative to JIRI_ROOT, that profiles are installed in")
}

func (cv *commonFlagValues) args() []string {
	a := append([]string{}, "--profiles-db="+cv.dbPath)
	a = append(a, "--profiles-dir="+cv.root)
	return a
}

type packagesFlagValues struct {
	commonFlagValues
	// The value of --target and --env
	target profiles.Target
	// Show commands for all required packages, rather than just the missing ones
	allPackages bool
	// Install the required packages
	installPackages bool
}

func initPackagesCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	initCommon(flags, &packagesFlags.commonFlagValues, installer, defaultDBPath, defaultProfilesPath)
	profiles.RegisterTargetAndEnvFlags(flags, &packagesFlags.target)
	flags.BoolVar(&packagesFlags.allPackages, "all", false, "print commands to install all required OS packages, not just those that are missing")
	flags.BoolVar(&packagesFlags.installPackages, "install", false, "install the requested packages. This may need to be run as root.")
	for _, name := range profilesmanager.Managers() {
		profilesmanager.LookupManager(name).AddFlags(flags, profiles.Install)
	}
}

func (pv *packagesFlagValues) args() []string {
	a := pv.commonFlagValues.args()
	if t := pv.target.String(); t != "" {
		a = append(a, "--target="+t)
	}
	if e := pv.target.CommandLineEnv().String(); e != "" {
		a = append(a, "--target="+e)
	}
	a = append(a, fmt.Sprintf("--%s=%v", "all", pv.allPackages))
	return append(a, fmt.Sprintf("--%s=%v", "install", pv.installPackages))
}

type installFlagValues struct {
	commonFlagValues
	// The value of --target and --env
	target profiles.Target
	// The value of --force
	force bool
}

func initInstallCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	initCommon(flags, &installFlags.commonFlagValues, installer, defaultDBPath, defaultProfilesPath)
	profiles.RegisterTargetAndEnvFlags(flags, &installFlags.target)
	flags.BoolVar(&installFlags.force, "force", false, "force install the profile even if it is already installed")
	for _, name := range profilesmanager.Managers() {
		profilesmanager.LookupManager(name).AddFlags(flags, profiles.Install)
	}
}

func (iv *installFlagValues) args() []string {
	a := iv.commonFlagValues.args()
	if t := iv.target.String(); t != "" {
		a = append(a, "--target="+t)
	}
	if e := iv.target.CommandLineEnv().String(); e != "" {
		a = append(a, "--target="+e)
	}
	return append(a, fmt.Sprintf("--%s=%v", "force", iv.force))
}

type uninstallFlagValues struct {
	commonFlagValues
	// The value of --target
	target profiles.Target
	// The value of --all-targets
	allTargets bool
	// The value of --v
	verbose bool
	// TODO(cnicolaou): add a flag to remove the profile only from the DB.
}

func initUninstallCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	initCommon(flags, &uninstallFlags.commonFlagValues, installer, defaultDBPath, defaultProfilesPath)
	profiles.RegisterTargetFlag(flags, &uninstallFlags.target)
	flags.BoolVar(&uninstallFlags.allTargets, "all-targets", false, "apply to all targets for the specified profile(s)")
	flags.BoolVar(&uninstallFlags.verbose, "v", false, "print more detailed information")
	for _, name := range profilesmanager.Managers() {
		profilesmanager.LookupManager(name).AddFlags(flags, profiles.Uninstall)
	}
}

func (uv *uninstallFlagValues) args() []string {
	a := uv.commonFlagValues.args()
	if uv.target.String() != "" {
		a = append(a, "--target="+uv.target.String())
	}
	a = append(a, fmt.Sprintf("--%s=%v", "all-targets", uv.allTargets))
	return append(a, fmt.Sprintf("--%s=%v", "v", uv.verbose))
}

type cleanupFlagValues struct {
	commonFlagValues
	// The value of --gc
	gc bool
	// The value of --rewrite-profiles-db
	rewriteDB bool
	// The value of --rm-all
	rmAll bool
	// The value of --v
	verbose bool
}

func initCleanupCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	initCommon(flags, &cleanupFlags.commonFlagValues, installer, defaultDBPath, defaultProfilesPath)
	flags.BoolVar(&cleanupFlags.gc, "gc", false, "uninstall profile targets that are older than the current default")
	flags.BoolVar(&cleanupFlags.rmAll, "rm-all", false, "remove profiles database and all profile generated output files.")
	flags.BoolVar(&cleanupFlags.rewriteDB, "rewrite-profiles-db", false, "rewrite the profiles database to use the latest schema version")
	flags.BoolVar(&cleanupFlags.verbose, "v", false, "print more detailed information")
}

func (cv *cleanupFlagValues) args() []string {
	return append(cv.commonFlagValues.args(),
		fmt.Sprintf("--%s=%v", "gc", cv.gc),
		fmt.Sprintf("--%s=%v", "rewrite-profiles-db", cv.rewriteDB),
		fmt.Sprintf("--%s=%v", "v", cv.verbose),
		fmt.Sprintf("--%s=%v", "rm-all", cv.rmAll))
}

type updateFlagValues struct {
	commonFlagValues
	// The value of --v
	verbose bool
}

func initUpdateCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	initCommon(flags, &updateFlags.commonFlagValues, installer, defaultDBPath, defaultProfilesPath)
	flags.BoolVar(&updateFlags.verbose, "v", false, "print more detailed information")
}

func (uv *updateFlagValues) args() []string {
	return append(uv.commonFlagValues.args(), fmt.Sprintf("--%s=%v", "v", uv.verbose))
}

type availableFlagValues struct {
	// The value of --v
	verbose bool
	// The value of --describe
	describe bool
}

func initAvailableCommand(flags *flag.FlagSet, installer, defaultDBPath, defaultProfilesPath string) {
	flags.BoolVar(&availableFlags.verbose, "v", false, "print more detailed information")
	flags.BoolVar(&availableFlags.describe, "describe", false, "print the profile description")
}

func (av *availableFlagValues) args() []string {
	return []string{
		fmt.Sprintf("--%s=%v", "v", av.verbose),
		fmt.Sprintf("--%s=%v", "describe", av.describe),
	}
}

var (
	packagesFlags    packagesFlagValues
	installFlags     installFlagValues
	uninstallFlags   uninstallFlagValues
	cleanupFlags     cleanupFlagValues
	updateFlags      updateFlagValues
	availableFlags   availableFlagValues
	profileInstaller string
	runSubcommands   bool
)

// RegisterManagementCommands registers the management subcommands:
// uninstall, install, update and cleanup.
func RegisterManagementCommands(parent *cmdline.Command, useSubcommands bool, installer, defaultDBPath, defaultProfilesPath string) {
	cmdOSPackages := newCmdOSPackages()
	cmdInstall := newCmdInstall()
	cmdUninstall := newCmdUninstall()
	cmdUpdate := newCmdUpdate()
	cmdCleanup := newCmdCleanup()
	cmdAvailable := newCmdAvailable()
	initPackagesCommand(&cmdOSPackages.Flags, installer, defaultDBPath, defaultProfilesPath)
	initInstallCommand(&cmdInstall.Flags, installer, defaultDBPath, defaultProfilesPath)
	initUninstallCommand(&cmdUninstall.Flags, installer, defaultDBPath, defaultProfilesPath)
	initUpdateCommand(&cmdUpdate.Flags, installer, defaultDBPath, defaultProfilesPath)
	initCleanupCommand(&cmdCleanup.Flags, installer, defaultDBPath, defaultProfilesPath)
	initAvailableCommand(&cmdAvailable.Flags, installer, defaultDBPath, defaultProfilesPath)
	parent.Children = append(parent.Children, cmdInstall, cmdOSPackages, cmdUninstall, cmdUpdate, cmdCleanup, cmdAvailable)
	profileInstaller = installer
	runSubcommands = useSubcommands
}

func findProfileSubcommands(jirix *jiri.X) []string {
	if !runSubcommands {
		return nil
	}
	cmds, _ := lookpath.LookPrefix(jirix.Env(), "jiri-profile-", nil)
	return cmds
}

func allAvailableManagers(jirix *jiri.X) ([]string, error) {
	names := profilesmanager.Managers()
	if profileInstaller != "" {
		return names, nil
	}
	subcommands := findProfileSubcommands(jirix)
	s := jirix.NewSeq()
	for _, sc := range subcommands {
		var out bytes.Buffer
		args := []string{"available"}
		if err := s.Capture(&out, nil).Last(sc, args...); err != nil {
			fmt.Fprintf(jirix.Stderr(), "failed to run %s %s: %v", sc, strings.Join(args, " "), err)
			return nil, err
		}
		mgrs := out.String()
		for _, m := range strings.Split(mgrs, ",") {
			names = append(names, strings.TrimSpace(m))
		}
	}
	return names, nil
}

// availableProfileManagers creates a profileManager for all available
// profiles, whether in this process or in a sub command.
func availableProfileManagers(jirix *jiri.X, dbpath string, args []string) ([]profileManager, *profiles.DB, error) {
	db := profiles.NewDB()
	if err := db.Read(jirix, dbpath); err != nil {
		fmt.Fprintf(jirix.Stderr(), "Failed to read profiles database %q: %v\n", dbpath, err)
		return nil, nil, err
	}
	mgrs := []profileManager{}
	names := args
	if len(names) == 0 {
		var err error
		names, err = allAvailableManagers(jirix)
		if err != nil {
			return nil, nil, err
		}
	}
	for _, name := range names {
		mgrs = append(mgrs, newProfileManager(name, db))
	}
	return mgrs, db, nil
}

// installedProfileManagers creates a profileManager for all installed
// profiles, whether in this process or in a sub command.
func installedProfileManagers(jirix *jiri.X, dbpath string, args []string) ([]profileManager, *profiles.DB, error) {
	db := profiles.NewDB()
	if err := db.Read(jirix, dbpath); err != nil {
		fmt.Fprintf(jirix.Stderr(), "Failed to read profiles database %q: %v\n", dbpath, err)
		return nil, nil, err
	}
	mgrs := []profileManager{}
	names := args
	if len(names) == 0 {
		names = db.Names()
	}
	for _, name := range names {
		mgrs = append(mgrs, newProfileManager(name, db))
	}
	return mgrs, db, nil
}

func targetAtDefaultVersion(mgr profiles.Manager, target profiles.Target) (profiles.Target, error) {
	def := target
	version, err := mgr.VersionInfo().Select(target.Version())
	if err != nil {
		return profiles.Target{}, err
	}
	def.SetVersion(version)
	return def, nil
}

func writeDB(jirix *jiri.X, db *profiles.DB, installer, path string) error {
	// If path is a directory and installer is empty, then do nothing,
	// otherwise write out the file.
	isdir := false
	fi, err := os.Stat(path)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
	} else {
		isdir = fi.IsDir()
	}
	if isdir {
		if installer != "" {
			// New setup with installers writing their own file in a directory
			return db.Write(jirix, installer, path)
		} else {
			// New setup, no installer, so don't write out the file.
			return nil
		}
	}
	if installer == "" {
		// Old setup with no installers and writing to a file.
		return db.Write(jirix, installer, path)
	}
	// New setup, but the directory doesn't exist yet.
	if err := os.MkdirAll(path, os.FileMode(0755)); err != nil {
		return err
	}
	return db.Write(jirix, installer, path)
}

func updateImpl(jirix *jiri.X, cl *updateFlagValues, args []string) error {
	mgrs, db, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	for _, mgr := range mgrs {
		if err := mgr.update(jirix, cl, root); err != nil {
			return err
		}
	}
	return writeDB(jirix, db, profileInstaller, cl.dbPath)
}

func cleanupImpl(jirix *jiri.X, cl *cleanupFlagValues, args []string) error {
	count := 0
	if cl.gc {
		count++
	}
	if cl.rewriteDB {
		count++
	}
	if cl.rmAll {
		count++
	}
	if count != 1 {
		fmt.Errorf("exactly one option must be specified")
	}
	mgrs, db, err := installedProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	for _, mgr := range mgrs {
		if err := mgr.cleanup(jirix, cl, root); err != nil {
			return err
		}
	}
	if !cl.rmAll {
		return writeDB(jirix, db, profileInstaller, cl.dbPath)
	}
	return nil
}

func packagesImpl(jirix *jiri.X, cl *packagesFlagValues, args []string) error {
	mgrs, _, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	cl.target.UseCommandLineEnv()
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	s := jirix.NewSeq()
	installPackages := cl.installPackages
	// Never ask a subcommand to install packages.
	cl.installPackages = false
	for _, mgr := range mgrs {
		cmds, err := mgr.packageCmds(jirix, cl, root)
		if err != nil {
			return err
		}
		for _, cmd := range cmds {
			if installPackages {
				if err := s.Verbose(true).Last(cmd[0], cmd[1:]...); err != nil {
					return err
				}
			} else {
				fmt.Fprintf(jirix.Stdout(), "%s\n", strings.TrimSpace(strings.Join(cmd, " ")))
			}
		}
	}
	return nil
}

func installImpl(jirix *jiri.X, cl *installFlagValues, args []string) error {
	mgrs, db, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	cl.target.UseCommandLineEnv()
	newMgrs := []profileManager{}
	for _, mgr := range mgrs {
		name := mgr.mgrName()
		if !cl.force {
			installer, profile := profiles.SplitProfileName(name)
			if p := db.LookupProfileTarget(installer, profile, cl.target); p != nil {
				fmt.Fprintf(jirix.Stdout(), "%v %v is already installed as %v\n", name, cl.target, p)
				continue
			}
		}
		newMgrs = append(newMgrs, mgr)
	}
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	for _, mgr := range newMgrs {
		if err := mgr.install(jirix, cl, root); err != nil {
			return err
		}
	}
	return writeDB(jirix, db, profileInstaller, cl.dbPath)
}

func uninstallImpl(jirix *jiri.X, cl *uninstallFlagValues, args []string) error {
	mgrs, db, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	if cl.allTargets && cl.target.IsSet() {
		fmt.Fprintf(jirix.Stdout(), "ignore target (%v) when used in conjunction with --all-targets\n", cl.target)
	}
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	for _, mgr := range mgrs {
		if err := mgr.uninstall(jirix, cl, root); err != nil {
			return err
		}
	}
	return writeDB(jirix, db, profileInstaller, cl.dbPath)
}

func availableImpl(jirix *jiri.X, cl *availableFlagValues, _ []string) error {
	if profileInstaller == "" {
		subcommands := findProfileSubcommands(jirix)
		if cl.verbose {
			fmt.Fprintf(jirix.Stdout(), "Available Subcommands: %s\n", strings.Join(subcommands, ", "))
		}
		s := jirix.NewSeq()
		args := []string{"available"}
		args = append(args, cl.args()...)
		out := bytes.Buffer{}
		for _, sc := range subcommands {
			if err := s.Capture(&out, nil).Last(sc, args...); err != nil {
				return err
			}
		}
		if s := strings.TrimSpace(out.String()); s != "" {
			fmt.Fprintln(jirix.Stdout(), s)
		}
	}
	mgrs := profilesmanager.Managers()
	if len(mgrs) == 0 {
		return nil
	}
	if cl.verbose {
		scname := ""
		if profileInstaller != "" {
			scname = profileInstaller + ": "
		}
		fmt.Fprintf(jirix.Stdout(), "%sAvailable Profiles:\n", scname)
		for _, name := range mgrs {
			mgr := profilesmanager.LookupManager(name)
			vi := mgr.VersionInfo()
			fmt.Fprintf(jirix.Stdout(), "%s: versions: %s\n", name, vi)
		}
	} else {
		if cl.describe {
			for _, name := range mgrs {
				mgr := profilesmanager.LookupManager(name)
				fmt.Fprintf(jirix.Stdout(), "%s: %s\n", name, strings.Replace(strings.TrimSpace(mgr.Info()), "\n", " ", -1))
			}
		} else {
			fmt.Fprintf(jirix.Stdout(), "%s\n", strings.Join(mgrs, ", "))
		}
	}
	return nil
}
