// 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 installer contains logic responsible for managing the device manager
// server, including setting it up / tearing it down, and starting / stopping
// it.
package installer

// When setting up the device manager installation, the installer creates a
// directory structure from which the device manager can be run.  It sets up:
//
// <installDir>                - provided when installer is invoked
//   dmroot/                   - created/owned by the installation
//     device-manager/         - will be the root for the device manager server;
//                               set as <Config.Root> (see comment in
//                               device_service.go for what goes under here)
//       info                  - json-encoded info about the running device manager (currently just the pid)
//       base/                 - initial installation of device manager
//         deviced             - link to deviced (self)
//         deviced.sh          - script to start the device manager
//       device-data/
//         persistent-args     - list of persistent arguments for the device
//                               manager (json encoded)
//       logs/                 - device manager logs will go here
//     current                 - set as <Config.CurrentLink>
//     creation_info           - json-encoded info about the binary that created the directory tree
//     agent_deviced.sh        - script to launch device manager under agent
//     security/               - security agent keeps credentials here
//       keys/
//       principal/
//     agent_logs/             - security agent logs
//       STDERR-<timestamp>
//       STDOUT-<timestamp>
//     service_description     - json-encoded sysinit device manager config
//     inithelper              - soft link to init helper
//
// TODO: we should probably standardize on '-' vs '_' for multi-word filename separators. Note any change
// in the name of creation_info will require some care to ensure the version check continues to work.

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"syscall"
	"time"

	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/services/application"
	"v.io/x/ref"
	"v.io/x/ref/services/device/deviced/internal/impl"
	"v.io/x/ref/services/device/deviced/internal/versioning"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/device/internal/sysinit"
)

// restartExitCode is the exit code that the device manager should return when it
// wants to be restarted by its parent (i.e., the security agent).
// This number is picked quasi-arbitrarily from the set of
// exit codes without prior special meanings.
const restartExitCode = 140

// dmRoot is the directory name where the device manager installs itself.
const dmRoot = "dmroot"

// InstallFrom takes a vanadium object name denoting an application service where
// a device manager application envelope can be obtained.  It downloads the
// latest version of the device manager and installs it.
func InstallFrom(origin string) error {
	// TODO(caprita): Implement.
	return nil
}

// initCommand verifies if init mode is enabled, and if so executes the
// appropriate sysinit command.  Returns whether init mode was detected, as well
// as any error encountered.
func initCommand(root, command string, stderr, stdout io.Writer) (bool, error) {
	sdFile := filepath.Join(root, "service_description")
	if _, err := os.Stat(sdFile); err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, fmt.Errorf("Stat(%v) failed: %v", sdFile, err)
	}
	helperLink := filepath.Join(root, "inithelper")
	cmd := exec.Command(helperLink, fmt.Sprintf("--service_description=%s", sdFile), command)
	if stderr != nil {
		cmd.Stderr = stderr
	}
	if stdout != nil {
		cmd.Stdout = stdout
	}
	if err := cmd.Run(); err != nil {
		return true, fmt.Errorf("Running init helper %v failed: %v", command, err)
	}
	return true, nil
}

// SelfInstall installs the device manager and configures it using the
// environment and the supplied command-line flags.
func SelfInstall(ctx *context.T, installDir, suidHelper, agent, initHelper, origin string, singleUser, sessionMode, init bool, args, env []string, stderr, stdout io.Writer) error {
	if os.Getenv(ref.EnvCredentials) != "" {
		return fmt.Errorf("Attempting to install device manager under agent with the %q environment variable set.", ref.EnvCredentials)
	}
	root := filepath.Join(installDir, dmRoot)
	if _, err := os.Stat(root); err == nil || !os.IsNotExist(err) {
		return fmt.Errorf("%v already exists", root)
	}
	deviceDir := filepath.Join(root, "device-manager", "base")
	perm := os.FileMode(0711)
	if err := os.MkdirAll(deviceDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", deviceDir, perm, err)
	}

	// save info about the binary creating this tree
	if err := versioning.SaveCreatorInfo(ctx, root); err != nil {
		return err
	}

	currLink := filepath.Join(root, "current")
	configState := &config.State{
		Name:        "dummy", // So that Validate passes.
		Root:        root,
		Origin:      origin,
		CurrentLink: currLink,
		Helper:      suidHelper,
	}
	if err := configState.Validate(); err != nil {
		return fmt.Errorf("invalid config %v: %v", configState, err)
	}
	var extraArgs []string
	if name, err := os.Hostname(); err == nil {
		extraArgs = append(extraArgs, fmt.Sprintf("--name=%q", naming.Join("devices", name)))
	}
	if !sessionMode {
		extraArgs = append(extraArgs, fmt.Sprintf("--restart-exit-code=%d", restartExitCode))
	}
	envelope := &application.Envelope{
		Args: append(extraArgs, args...),
		// TODO(caprita): Cleaning up env vars to avoid picking up all
		// the garbage from the user's env.
		// Alternatively, pass the env vars meant specifically for the
		// device manager in a different way.
		Env: impl.VanadiumEnvironment(env),
	}
	if err := impl.SavePersistentArgs(root, envelope.Args); err != nil {
		return err
	}
	if err := impl.LinkSelf(deviceDir, "deviced"); err != nil {
		return err
	}
	configSettings, err := configState.Save(nil)
	if err != nil {
		return fmt.Errorf("failed to serialize config %v: %v", configState, err)
	}
	logs := filepath.Join(root, "device-manager", "logs")
	if err := impl.GenerateScript(deviceDir, configSettings, envelope, logs); err != nil {
		return err
	}

	// TODO(caprita): Test the device manager we just installed.
	if err := impl.UpdateLink(filepath.Join(deviceDir, "deviced.sh"), currLink); err != nil {
		return err
	}

	if err := generateAgentScript(root, agent, currLink, singleUser, sessionMode); err != nil {
		return err
	}
	if init {
		agentScript := filepath.Join(root, "agent_deviced.sh")
		currentUser, err := user.Current()
		if err != nil {
			return err
		}
		sd := &sysinit.ServiceDescription{
			Service:     "deviced",
			Description: "Vanadium Device Manager",
			Binary:      agentScript,
			Command:     []string{agentScript},
			User:        currentUser.Username,
		}
		sdFile := filepath.Join(root, "service_description")
		if err := sd.SaveTo(sdFile); err != nil {
			return fmt.Errorf("SaveTo for %v failed: %v", sd, err)
		}
		helperLink := filepath.Join(root, "inithelper")
		if err := os.Symlink(initHelper, helperLink); err != nil {
			return fmt.Errorf("Symlink(%v, %v) failed: %v", initHelper, helperLink, err)
		}
		if initMode, err := initCommand(root, "install", stderr, stdout); err != nil {
			return err
		} else if !initMode {
			return fmt.Errorf("enabling init mode failed")
		}
	}
	return nil
}

func generateAgentScript(workspace, agent, currLink string, singleUser, sessionMode bool) error {
	securityDir := filepath.Join(workspace, "security")
	principalDir := filepath.Join(securityDir, "principal")
	keyDir := filepath.Join(securityDir, "keys")
	perm := os.FileMode(0700)
	if err := os.MkdirAll(principalDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", principalDir, perm, err)
	}
	if err := os.MkdirAll(keyDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", keyDir, perm, err)
	}
	logs := filepath.Join(workspace, "agent_logs")
	if err := os.MkdirAll(logs, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", logs, perm, err)
	}
	stdoutLog, stderrLog := filepath.Join(logs, "STDOUT"), filepath.Join(logs, "STDERR")
	// TODO(caprita): Switch all our generated bash scripts to use templates.
	output := "#!/bin/bash\n"
	output += "if [ -z \"$DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR\" ]; then\n"
	output += fmt.Sprintf("  TIMESTAMP=$(%s)\n", impl.DateCommand)
	output += fmt.Sprintf("  exec > %s-$TIMESTAMP 2> %s-$TIMESTAMP\n", stdoutLog, stderrLog)
	output += "fi\n"
	output += fmt.Sprintf("%s=%q ", ref.EnvCredentials, principalDir)
	// Escape the path to the binary; %q uses Go-syntax escaping, but it's
	// close enough to Bash that we're using it as an approximation.
	//
	// TODO(caprita/rthellend): expose and use shellEscape (from
	// v.io/x/ref/services/debug/debug/impl.go) instead.
	output += fmt.Sprintf("exec %q --log_dir=%q ", agent, logs)
	if singleUser {
		output += "--no-passphrase "
	}
	if !sessionMode {
		output += fmt.Sprintf("--restart-exit-code=!0 ")
	}
	output += fmt.Sprintf("--additional-principals=%q %q", keyDir, currLink)
	path := filepath.Join(workspace, "agent_deviced.sh")
	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
		return fmt.Errorf("WriteFile(%v) failed: %v", path, err)
	}
	// TODO(caprita): Put logs under dmroot/device-manager/logs.
	return nil
}

// Uninstall undoes SelfInstall, removing the device manager's installation
// directory.
func Uninstall(ctx *context.T, installDir, helperPath string, stdout, stderr io.Writer) error {
	// TODO(caprita): ensure device is stopped?

	root := filepath.Join(installDir, dmRoot)
	if _, err := initCommand(root, "uninstall", stdout, stderr); err != nil {
		return err
	}
	impl.InitSuidHelper(ctx, helperPath)
	return impl.DeleteFileTree(ctx, root, stdout, stderr)
}

// Start starts the device manager.
func Start(ctx *context.T, installDir string, stderr, stdout io.Writer) error {
	// TODO(caprita): make sure it's not already running?

	root := filepath.Join(installDir, dmRoot)

	if initMode, err := initCommand(root, "start", stderr, stdout); err != nil {
		return err
	} else if initMode {
		return nil
	}

	if os.Getenv(ref.EnvCredentials) != "" {
		return fmt.Errorf("Attempting to run device manager under agent with the %q environment variable set.", ref.EnvCredentials)
	}
	agentScript := filepath.Join(root, "agent_deviced.sh")
	cmd := exec.Command(agentScript)
	if stderr != nil {
		cmd.Stderr = stderr
	}
	if stdout != nil {
		cmd.Stdout = stdout
	}
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Start failed: %v", err)
	}

	// Save away the agent's pid to be used for stopping later ...
	if cmd.Process.Pid == 0 {
		fmt.Fprintf(stderr, "Unable to get a pid for successfully-started agent!")
		return nil // We tolerate the error, at the expense of being able to stop later
	}
	mi := &impl.ManagerInfo{
		Pid: cmd.Process.Pid,
	}
	if err := impl.SaveManagerInfo(filepath.Join(root, "agent-deviced"), mi); err != nil {
		return fmt.Errorf("failed to save info for agent-deviced: %v", err)
	}

	return nil
}

// Stop stops the device manager.
func Stop(ctx *context.T, installDir string, stderr, stdout io.Writer) error {
	root := filepath.Join(installDir, dmRoot)
	if initMode, err := initCommand(root, "stop", stderr, stdout); err != nil {
		return err
	} else if initMode {
		return nil
	}

	agentPid, devmgrPid := 0, 0

	// Load the agent pid
	info, err := impl.LoadManagerInfo(filepath.Join(root, "agent-deviced"))
	if err != nil {
		return fmt.Errorf("loadManagerInfo failed for agent-deviced: %v", err)
	}
	if syscall.Kill(info.Pid, 0) == nil { // Save the pid if it's currently live
		agentPid = info.Pid
	}

	// Load the device manager pid
	info, err = impl.LoadManagerInfo(filepath.Join(root, "device-manager"))
	if err != nil {
		return fmt.Errorf("loadManagerInfo failed for device-manager: %v", err)
	}
	if syscall.Kill(info.Pid, 0) == nil { // Save the pid if it's currently live
		devmgrPid = info.Pid
	}

	if agentPid == 0 && devmgrPid == 0 {
		return fmt.Errorf("stop could not find any live pids to stop")
	}

	// Set up waiters for each nonzero pid. This ensures that exiting processes are reaped when
	// the agent or device manager happen to be children of this process. (Not commonly the case,
	// but it does occur in the impl test.)
	if agentPid != 0 {
		go func() {
			if p, err := os.FindProcess(agentPid); err == nil {
				p.Wait()
			}
		}()
	}
	if devmgrPid != 0 {
		go func() {
			if p, err := os.FindProcess(devmgrPid); err == nil {
				p.Wait()
			}
		}()
	}

	// First, send SIGINT to the agent. We expect both the agent and the device manager to
	// exit as a result within 15 seconds
	if agentPid != 0 {
		if err = syscall.Kill(agentPid, syscall.SIGINT); err != nil {
			return fmt.Errorf("sending SIGINT to %d: %v", agentPid, err)
		}
		for i := 0; i < 30 && syscall.Kill(agentPid, 0) == nil; i++ {
			time.Sleep(500 * time.Millisecond)
			if i%5 == 4 {
				fmt.Fprintf(stderr, "waiting for agent (pid %d) to die...\n", agentPid)
			}
		}
		if syscall.Kill(agentPid, 0) == nil { // agent is still alive, resort to brute force
			fmt.Fprintf(stderr, "sending SIGKILL to agent %d\n", agentPid)
			if err = syscall.Kill(agentPid, syscall.SIGKILL); err != nil {
				fmt.Fprintf(stderr, "Sending SIGKILL to %d: %v\n", agentPid, err)
				// not returning here, so that we check & kill the device manager too
			}
		}
	}

	// If the device manager is still alive, forcibly kill it
	if syscall.Kill(devmgrPid, 0) == nil {
		fmt.Fprintf(stderr, "sending SIGKILL to device manager %d\n", devmgrPid)
		if err = syscall.Kill(devmgrPid, syscall.SIGKILL); err != nil {
			return fmt.Errorf("sending SIGKILL to device manager %d: %v", devmgrPid, err)
		}
	}

	// By now, nothing should be alive. Check and report
	if agentPid != 0 && syscall.Kill(agentPid, 0) == nil {
		return fmt.Errorf("multiple attempts to kill agent pid %d have failed", agentPid)
	}
	if devmgrPid != 0 && syscall.Kill(devmgrPid, 0) == nil {
		return fmt.Errorf("multiple attempts to kill device manager pid %d have failed", devmgrPid)
	}

	// Should we remove the agentd and deviced info files here? Not removing them
	// increases the chances that we later rerun stop and shoot some random process. Removing
	// them makes it impossible to run stop a second time (although that shouldn't be necessary)
	// and also introduces the potential for a race condition if a new agent/deviced are started
	// right after these ones get killed.
	//
	// TODO: Reconsider this when we add stronger protection to make sure that the pids being
	// signalled are in fact the agent and/or device manager

	// Process was killed succesfully
	return nil
}
