package dkms

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"cos.googlesource.com/cos/tools.git/src/pkg/fs"
	"cos.googlesource.com/cos/tools.git/src/pkg/gcs"
	"cos.googlesource.com/cos/tools.git/src/pkg/utils"
	"github.com/golang/glog"
)

// Install installs all of the modules from a DKMS package into the install
// tree.
//
// This will add and build the package if it is not already added and built.
//
// For each module in the package, this will check if the version being
// installed is newer than the version of the module which is already
// installed, if applicable. If the module version is older than the one
// already installed, this will skip installing that module and emit an info
// message. options.ForceVersionOverride can be set to bypass the version
// check and install the module anyway.
//
// If options.ModprobeOnInstall is passed, then modprobe will be called on
// the module after it is copied to the install tree to insert it into the
// running kernel.
func Install(pkg *Package, options *Options) error {
	// This must happen first in order to set the package config.
	if err := Build(pkg, options); err != nil {
		return err
	}

	if IsInstalled(pkg) {
		if !options.Force {
			glog.Info("package already installed; skipping installation")
			return nil
		}

		if err := Uninstall(pkg); err != nil {
			return fmt.Errorf("failed to uninstall package before forcing reinstall: %v", err)
		}
	}

	glog.Infof("installing package %s-%s", pkg.Name, pkg.Version)
	if pkg.Config.PreInstall != "" {
		if err := utils.RunCommandString(pkg.BuildDir(), pkg.Config.PreInstall); err != nil {
			return fmt.Errorf("failed to run pre-install script: %v", err)
		}
	}

	var modulesToInstall []Module
	if options.ForceVersionOverride {
		modulesToInstall = pkg.Config.Modules
	} else {
		modules, err := ModulesToInstall(pkg.Config.Modules, pkg.Trees.Install)
		if err != nil {
			return err
		}
		modulesToInstall = modules
	}

	for _, module := range modulesToInstall {
		srcPath := module.BuiltPath()
		dstPath := module.DestPath()

		glog.Infof("copying %s to %s", srcPath, dstPath)
		if err := os.MkdirAll(filepath.Dir(dstPath), 0777); err != nil {
			return err
		}

		if err := fs.CopyFile(srcPath, dstPath, 0666); err != nil {
			return err
		}
	}

	if options.InsertOnInstall {
		kernelModulePaths, err := FindKernelModules(pkg.Trees.KernelModules)
		if err != nil {
			return err
		}
		installedModulePaths, err := FindKernelModules(pkg.Trees.Install)
		if err != nil {
			return err
		}

		modulePaths := make(map[string]string)
		for module, path := range kernelModulePaths {
			modulePaths[module] = path
		}
		// Modules in the install tree should take precedence over ones in the kernel tree
		for module, path := range installedModulePaths {
			modulePaths[module] = path
		}

		var moduleNames []string
		for _, module := range modulesToInstall {
			moduleNames = append(moduleNames, module.DestName)
		}

		if err := InsertModules(moduleNames, modulePaths, pkg.ModuleParams); err != nil {
			return err
		}
	}

	if options.ModprobeOnInstall {
		if !options.NoDepmod {
			if err := Depmod(); err != nil {
				return err
			}
		}

		if err := ModprobeModules(pkg.Config.Modules); err != nil {
			return err
		}
	}

	if pkg.Config.PostInstall != "" {
		if err := utils.RunCommandString(pkg.BuildDir(), pkg.Config.PostInstall); err != nil {
			return fmt.Errorf("failed to run post-install script: %v", err)
		}
	}

	return nil
}

// CachedInstall installs all of the modules from a DKMS package into the
// install tree, using CachedBuild to build the package if necessary.
//
// See Install for more information on how modules are installed locally.
func CachedInstall(ctx context.Context, pkg *Package, cache *gcs.GCSBucket, options *Options) error {
	if err := CachedBuild(ctx, pkg, cache, options); err != nil {
		return err
	}

	return Install(pkg, options)
}

// ModulesToInstall returns the list of modules which should be installed.
//
// This takes a list of candidate modules to install and a directory where
// they would be installed and checks for each module if there is a newer
// version of that module already installed. If there is a newer or equal
// version already installed, the module is omitted from the output list
// and an info message is emitted.
func ModulesToInstall(modules []Module, installTree string) ([]Module, error) {
	installedKernelModules, err := FindKernelModules(installTree)
	if err != nil {
		return nil, fmt.Errorf("could not find all installed kernel modules")
	}

	var result []Module
	for _, module := range modules {
		installName := module.DestName + ".ko"
		installedModulePath, ok := installedKernelModules[installName]
		if !ok {
			result = append(result, module)
			continue // module is not yet installed
		}

		installedVersion, err := ModuleVersion(installedModulePath)
		if err != nil {
			return nil, fmt.Errorf("could not determine installed module version for module %s: %s", module.DestName, err)
		}

		builtVersion, err := ModuleVersion(module.BuiltPath())
		if err != nil {
			return nil, fmt.Errorf("could not determine built module version for module %s: %v", module.BuiltName, err)
		}

		comparison := CompareVersions(builtVersion, installedVersion)
		if comparison < 0 {
			glog.Infof(
				"installed version of module %s is newer than built version (%s > %s); not reinstalling; pass --force-version-override to install anyway",
				module.DestName, installedVersion, builtVersion,
			)
		} else if comparison == 0 {
			glog.Infof(
				"module %s is already installed with version %s; not reinstalling; pass --force-version-override to install anyway",
				module.DestName, installedVersion,
			)
		} else {
			result = append(result, module)
		}
	}

	return result, nil
}

// IsInstalled returns whether or not all of a package's modules have been
// installed.
//
// If the package does not have its config set, this returns false.
func IsInstalled(pkg *Package) bool {
	if pkg.Config == nil {
		return false
	}

	for _, module := range pkg.Config.Modules {
		if !fs.IsFile(module.DestPath()) {
			return false
		}
	}

	return true
}

