// 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 _, err := targetAtDefaultVersion(mgr, *target); err == nil {
				// Target with default version is already installed.
				continue
			}
			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)
	}
}
