// 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

import (
	"fmt"
	"strings"

	"v.io/jiri/jiri"
	"v.io/jiri/profiles"
	"v.io/jiri/profiles/profilesmanager"
	"v.io/jiri/runutil"
)

// profileManager is implemented for both in-process and sub-command
// implemented profiles.
type profileManager interface {
	install(jirix *jiri.X, cl *installFlagValues, root jiri.RelPath) error
	uninstall(jirix *jiri.X, cl *uninstallFlagValues, root jiri.RelPath) error
	update(jirix *jiri.X, cl *updateFlagValues, root jiri.RelPath) error
	cleanup(jirix *jiri.X, cl *cleanupFlagValues, root jiri.RelPath) error
	mgrName() string
}

func newProfileManager(name string, db *profiles.DB) profileManager {
	installer, profile := profiles.SplitProfileName(name)
	installer = strings.TrimSpace(installer)
	if len(installer) == 0 || installer == profileInstaller {
		return &inproc{installer, profile, name, db}
	}
	return &subcommand{installer, profile, name, db}
}

type inproc struct {
	installer, name, qname string
	db                     *profiles.DB
}

func (ip *inproc) mgrName() string {
	return ip.qname
}

func (ip *inproc) install(jirix *jiri.X, cl *installFlagValues, root jiri.RelPath) error {
	mgr := profilesmanager.LookupManager(ip.qname)
	if mgr == nil {
		return fmt.Errorf("profile %v is not available via this installer %q", ip.qname, ip.installer)
	}
	def, err := targetAtDefaultVersion(mgr, cl.target)
	if err != nil {
		return err
	}
	err = mgr.Install(jirix, ip.db, root, def)
	logResult(jirix, "Install", mgr, def, err)
	return err
}

func (ip *inproc) uninstall(jirix *jiri.X, cl *uninstallFlagValues, root jiri.RelPath) error {
	profile := ip.db.LookupProfile(ip.installer, ip.name)
	if profile == nil {
		fmt.Fprintf(jirix.Stdout(), "%s is not installed\n", ip.qname)
		return nil
	}
	mgr := profilesmanager.LookupManager(ip.qname)
	var targets []*profiles.Target
	if cl.allTargets {
		targets = profile.Targets()
	} else {
		def, err := targetAtDefaultVersion(mgr, cl.target)
		if err != nil {
			return err
		}
		targets = []*profiles.Target{&def}
	}
	for _, target := range targets {
		if err := mgr.Uninstall(jirix, ip.db, root, *target); err != nil {
			logResult(jirix, "Uninstall", mgr, *target, err)
			return err
		}
		logResult(jirix, "Uninstall", mgr, *target, nil)
	}
	return nil
}

func (ip *inproc) update(jirix *jiri.X, cl *updateFlagValues, root jiri.RelPath) error {
	profile := ip.db.LookupProfile(ip.installer, ip.name)
	if profile == nil {
		// silently ignore uninstalled profile.
		return nil
	}
	mgr := profilesmanager.LookupManager(ip.qname)
	vi := mgr.VersionInfo()
	for _, target := range profile.Targets() {
		if vi.IsTargetOlderThanDefault(target.Version()) {
			if cl.verbose {
				fmt.Fprintf(jirix.Stdout(), "Updating %s %s from %q to %s\n", ip.qname, target, target.Version(), vi)
			}
			target.SetVersion(vi.Default())
			err := mgr.Install(jirix, ip.db, root, *target)
			logResult(jirix, "Update", mgr, *target, err)
			if err != nil {
				return err
			}
		} else {
			if cl.verbose {
				fmt.Fprintf(jirix.Stdout(), "%s %s at %q is up to date(%s)\n", ip.qname, target, target.Version(), vi)
			}
		}
	}
	return nil
}

func cleanupGC(jirix *jiri.X, db *profiles.DB, root jiri.RelPath, verbose bool, name string) error {
	mgr := profilesmanager.LookupManager(name)
	if mgr == nil {
		fmt.Fprintf(jirix.Stderr(), "%s is not linked into this binary\n", name)
		return nil
	}
	vi := mgr.VersionInfo()
	installer, profileName := profiles.SplitProfileName(name)
	profile := db.LookupProfile(installer, profileName)
	for _, target := range profile.Targets() {
		if vi.IsTargetOlderThanDefault(target.Version()) {
			err := mgr.Uninstall(jirix, db, root, *target)
			logResult(jirix, "Cleanup: -gc", mgr, *target, err)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func cleanupRmAll(jirix *jiri.X, db *profiles.DB, root jiri.RelPath) error {
	s := jirix.NewSeq()
	if err := s.AssertFileExists(db.Path()).Remove(db.Path()).Done(); err != nil && !runutil.IsNotExist(err) {
		return err
	}
	d := root.Abs(jirix)
	err := s.AssertDirExists(d).
		Run("chmod", "-R", "u+w", d).
		RemoveAll(d).
		Done()
	fmt.Fprintf(jirix.Stdout(), "Cleanup: -rm-all: ")
	if err == nil || runutil.IsNotExist(err) {
		fmt.Fprintf(jirix.Stdout(), "success\n")
		return nil
	} else {
		fmt.Fprintf(jirix.Stdout(), "%v\n", err)
	}
	return err
}

func (ip *inproc) cleanup(jirix *jiri.X, cl *cleanupFlagValues, root jiri.RelPath) error {
	if cl.gc {
		if cl.verbose {
			fmt.Fprintf(jirix.Stdout(), "Removing targets older than the default version for %s\n", ip.qname)
		}
		if err := cleanupGC(jirix, ip.db, root, cl.verbose, ip.qname); err != nil {
			return fmt.Errorf("gc: %v", err)
		}
	}
	if cl.rmAll {
		if cl.verbose {
			fmt.Fprintf(jirix.Stdout(), "Removing profile manifest and all profile output files\n")
		}
		if err := cleanupRmAll(jirix, ip.db, root); err != nil {
			return err
		}
	}
	return nil
}

type subcommand struct {
	installer, profile, qname string
	db                        *profiles.DB
}

func (sc *subcommand) mgrName() string {
	return sc.qname
}

func (sc *subcommand) run(jirix *jiri.X, verb string, args []string) error {
	cl := []string{"profile-" + sc.installer, verb}
	cl = append(cl, args...)
	cl = append(cl, sc.qname)
	return jirix.NewSeq().Capture(jirix.Stdout(), jirix.Stderr()).Last("jiri", cl...)
}

func (sc *subcommand) install(jirix *jiri.X, cl *installFlagValues, root jiri.RelPath) error {
	return sc.run(jirix, "install", cl.args())
}

func (sc *subcommand) uninstall(jirix *jiri.X, cl *uninstallFlagValues, root jiri.RelPath) error {
	return sc.run(jirix, "uninstall", cl.args())
}

func (sc *subcommand) update(jirix *jiri.X, cl *updateFlagValues, root jiri.RelPath) error {
	return sc.run(jirix, "update", cl.args())
}

func (sc *subcommand) cleanup(jirix *jiri.X, cl *cleanupFlagValues, root jiri.RelPath) error {
	return sc.run(jirix, "cleanup", cl.args())
}

func logResult(jirix *jiri.X, action string, mgr profiles.Manager, target profiles.Target, err error) {
	fmt.Fprintf(jirix.Stdout(), "%s: %s %s: ", action, profiles.QualifiedProfileName(mgr.Installer(), mgr.Name()), target)
	if err == nil {
		fmt.Fprintf(jirix.Stdout(), "success\n")
	} else {
		fmt.Fprintf(jirix.Stdout(), "%v\n", err)
	}
}
