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

// The device invoker is responsible for managing the state of the device
// manager itself.  The implementation expects that the device manager
// installations are all organized in the following directory structure:
//
// <config.Root>/
//   device-manager/
//     info                    - metadata for the device manager (such as object
//                               name and process id)
//     logs/                   - device manager logs
//       STDERR-<timestamp>    - one for each execution of device manager
//       STDOUT-<timestamp>    - one for each execution of device manager
//     <version 1 timestamp>/  - timestamp of when the version was downloaded
//       deviced               - the device manager binary
//       deviced.sh            - a shell script to start the binary
//     <version 2 timestamp>
//     ...
//     device-data/
//       acls/
//         data
//         signature
//     associated.accounts
//       persistent-args       - list of persistent arguments for the device
//                               manager (json encoded)
//
// The device manager is always expected to be started through the symbolic link
// passed in as config.CurrentLink, which is monitored by an init daemon. This
// provides for simple and robust updates.
//
// To update the device manager to a newer version, a new workspace is created
// and the symlink is updated to the new deviced.sh script. Similarly, to revert
// the device manager to a previous version, all that is required is to update
// the symlink to point to the previous deviced.sh script.

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
	"time"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/services/application"
	"v.io/v23/services/binary"
	"v.io/v23/services/device"
	"v.io/v23/verror"
	"v.io/x/ref"
	vexec "v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	vsecurity "v.io/x/ref/lib/security"
	"v.io/x/ref/services/agent/agentlib"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/device/internal/errors"
	"v.io/x/ref/services/profile"
)

type updatingState struct {
	// updating is a flag that records whether this instance of device
	// manager is being updated.
	updating bool
	// updatingMutex is a lock for coordinating concurrent access to
	// <updating>.
	updatingMutex sync.Mutex
}

func newUpdatingState() *updatingState {
	return new(updatingState)
}

func (u *updatingState) testAndSetUpdating() bool {
	u.updatingMutex.Lock()
	defer u.updatingMutex.Unlock()
	if u.updating {
		return true
	}
	u.updating = true
	return false
}

func (u *updatingState) unsetUpdating() {
	u.updatingMutex.Lock()
	u.updating = false
	u.updatingMutex.Unlock()
}

// deviceService implements the Device manager's Device interface.
type deviceService struct {
	updating       *updatingState
	restartHandler func()
	callback       *callbackState
	config         *config.State
	disp           *dispatcher
	uat            BlessingSystemAssociationStore
	securityAgent  *securityAgentState
	tidying        chan<- tidyRequests
}

// ManagerInfo holds state about a running device manager or a running agentd
type ManagerInfo struct {
	Pid int
}

func SaveManagerInfo(dir string, info *ManagerInfo) error {
	jsonInfo, err := json.Marshal(info)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Marshal(%v) failed: %v", info, err))
	}
	if err := os.MkdirAll(dir, os.FileMode(0700)); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("MkdirAll(%v) failed: %v", dir, err))
	}
	infoPath := filepath.Join(dir, "info")
	if err := ioutil.WriteFile(infoPath, jsonInfo, 0600); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("WriteFile(%v) failed: %v", infoPath, err))
	}
	return nil
}

func LoadManagerInfo(dir string) (*ManagerInfo, error) {
	infoPath := filepath.Join(dir, "info")
	info := new(ManagerInfo)
	if infoBytes, err := ioutil.ReadFile(infoPath); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("ReadFile(%v) failed: %v", infoPath, err))
	} else if err := json.Unmarshal(infoBytes, info); err != nil {
		return nil, verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Unmarshal(%v) failed: %v", infoBytes, err))
	}
	return info, nil
}

func SavePersistentArgs(root string, args []string) error {
	dir := filepath.Join(root, "device-manager", "device-data")
	if err := os.MkdirAll(dir, 0700); err != nil {
		return fmt.Errorf("MkdirAll(%q) failed: %v", dir, err)
	}
	data, err := json.Marshal(args)
	if err != nil {
		return fmt.Errorf("Marshal(%v) failed: %v", args, err)
	}
	fileName := filepath.Join(dir, "persistent-args")
	return ioutil.WriteFile(fileName, data, 0600)
}

func loadPersistentArgs(root string) ([]string, error) {
	fileName := filepath.Join(root, "device-manager", "device-data", "persistent-args")
	bytes, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	args := []string{}
	if err := json.Unmarshal(bytes, &args); err != nil {
		return nil, fmt.Errorf("json.Unmarshal(%v) failed: %v", bytes, err)
	}
	return args, nil
}

func (*deviceService) Describe(*context.T, rpc.ServerCall) (device.Description, error) {
	return Describe()
}

func (*deviceService) IsRunnable(_ *context.T, _ rpc.ServerCall, description binary.Description) (bool, error) {
	deviceProfile, err := ComputeDeviceProfile()
	if err != nil {
		return false, err
	}
	binaryProfiles := make([]*profile.Specification, 0)
	for name, _ := range description.Profiles {
		profile, err := getProfile(name)
		if err != nil {
			return false, err
		}
		binaryProfiles = append(binaryProfiles, profile)
	}
	result := matchProfiles(deviceProfile, binaryProfiles)
	return len(result.Profiles) > 0, nil
}

func (*deviceService) Reset(_ *context.T, _ rpc.ServerCall, deadline time.Duration) error {
	// TODO(jsimsa): Implement.
	return nil
}

// getCurrentFileInfo returns the os.FileInfo for both the symbolic link
// CurrentLink, and the device script in the workspace that this link points to.
func (s *deviceService) getCurrentFileInfo() (os.FileInfo, string, error) {
	path := s.config.CurrentLink
	link, err := os.Lstat(path)
	if err != nil {
		return nil, "", verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("Lstat(%v) failed: %v", path, err))
	}
	scriptPath, err := filepath.EvalSymlinks(path)
	if err != nil {
		return nil, "", verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("EvalSymlinks(%v) failed: %v", path, err))
	}
	return link, scriptPath, nil
}

func (s *deviceService) revertDeviceManager(ctx *context.T) error {
	if err := UpdateLink(s.config.Previous, s.config.CurrentLink); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("UpdateLink failed: %v", err))
	}
	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (s *deviceService) newLogfile(prefix string) (*os.File, error) {
	d := filepath.Join(s.config.Root, "device_test_logs")
	if _, err := os.Stat(d); err != nil {
		if err := os.MkdirAll(d, 0700); err != nil {
			return nil, err
		}
	}
	f, err := ioutil.TempFile(d, "__device_impl_test__"+prefix)
	if err != nil {
		return nil, err
	}
	return f, nil
}

// TODO(cnicolaou): would this be better implemented using the modules
// framework now that it exists?
func (s *deviceService) testDeviceManager(ctx *context.T, workspace string, envelope *application.Envelope) error {
	path := filepath.Join(workspace, "deviced.sh")
	cmd := exec.Command(path)
	cmd.Env = []string{"DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR=1"}

	for k, v := range map[string]*io.Writer{
		"stdout": &cmd.Stdout,
		"stderr": &cmd.Stderr,
	} {
		// Using a log file makes it less likely that stdout and stderr
		// output will be lost if the child crashes.
		file, err := s.newLogfile(fmt.Sprintf("deviced-test-%s", k))
		if err != nil {
			return err
		}
		fName := file.Name()
		defer os.Remove(fName)
		*v = file

		defer func(k string) {
			if f, err := os.Open(fName); err == nil {
				scanner := bufio.NewScanner(f)
				for scanner.Scan() {
					ctx.Infof("[testDeviceManager %s] %s", k, scanner.Text())
				}
			}
		}(k)
	}

	// Setup up the child process callback.
	callbackState := s.callback
	listener := callbackState.listenFor(mgmt.ChildNameConfigKey)
	defer listener.cleanup()
	cfg := vexec.NewConfig()

	cfg.Set(mgmt.ParentNameConfigKey, listener.name())
	cfg.Set(mgmt.ProtocolConfigKey, "tcp")
	cfg.Set(mgmt.AddressConfigKey, "127.0.0.1:0")

	var p security.Principal
	var agentHandle []byte
	if s.securityAgent != nil {
		// TODO(rthellend): Cleanup principal
		handle, conn, err := s.securityAgent.keyMgrAgent.NewPrincipal(ctx, false)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("NewPrincipal() failed %v", err))
		}
		agentHandle = handle
		var cancel func()
		if p, cancel, err = agentPrincipal(ctx, conn); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("agentPrincipal failed: %v", err))
		}
		defer cancel()

	} else {
		credentialsDir := filepath.Join(workspace, "credentials")
		var err error
		if p, err = vsecurity.CreatePersistentPrincipal(credentialsDir, nil); err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("CreatePersistentPrincipal(%v, nil) failed: %v", credentialsDir, err))
		}
		cmd.Env = append(cmd.Env, ref.EnvCredentials+"="+credentialsDir)
	}
	dmPrincipal := v23.GetPrincipal(ctx)
	dmBlessings, err := dmPrincipal.Bless(p.PublicKey(), dmPrincipal.BlessingStore().Default(), "testdm", security.UnconstrainedUse())
	if err := p.BlessingStore().SetDefault(dmBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.SetDefault() failed: %v", err))
	}
	if _, err := p.BlessingStore().Set(dmBlessings, security.AllPrincipals); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("BlessingStore.Set() failed: %v", err))
	}
	if err := p.AddToRoots(dmBlessings); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("AddToRoots() failed: %v", err))
	}

	if s.securityAgent != nil {
		file, err := s.securityAgent.keyMgrAgent.NewConnection(agentHandle)
		if err != nil {
			return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("NewConnection(%v) failed: %v", agentHandle, err))
		}
		defer file.Close()

		fd := len(cmd.ExtraFiles) + vexec.FileOffset
		cmd.ExtraFiles = append(cmd.ExtraFiles, file)
		// TODO: This should use the same network as the agent we're using,
		// not whatever this process was compiled with.
		ep := agentlib.AgentEndpoint(fd)
		cfg.Set(mgmt.SecurityAgentEndpointConfigKey, ep)
	}

	handle := vexec.NewParentHandle(cmd, vexec.ConfigOpt{cfg})
	// Start the child process.
	if err := handle.Start(); err != nil {
		ctx.Errorf("Start() failed: %v", err)
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Start() failed: %v", err))
	}
	defer func() {
		if err := handle.Clean(); err != nil {
			ctx.Errorf("Clean() failed: %v", err)
		}
	}()

	// Wait for the child process to start.
	if err := handle.WaitForReady(childReadyTimeout); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WaitForReady(%v) failed: %v", childReadyTimeout, err))
	}

	// Watch for the exit of the child. Failures could cause it to happen at any time
	waitchan := make(chan error, 1)
	go func() {
		// Wait timeout needs to be long enough to give the rest of the operations time to run
		err := handle.Wait(2*childReadyTimeout + childWaitTimeout)
		if err != nil {
			waitchan <- verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("new device manager failed to exit cleanly: %v", err))
		}
		close(waitchan)
		listener.stop()
	}()

	childName, err := listener.waitForValue(childReadyTimeout)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("waitForValue(%v) failed: %v", childReadyTimeout, err))
	}
	// Check that invoking Delete() succeeds.
	childName = naming.Join(childName, "device")
	dmClient := device.DeviceClient(childName)
	if err := dmClient.Delete(ctx); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("Delete() failed: %v", err))
	}
	if err := <-waitchan; err != nil {
		return err
	}
	return nil
}

// TODO(caprita): Move this to util.go since device_installer is also using it now.

func GenerateScript(workspace string, configSettings []string, envelope *application.Envelope, logs string) error {
	// TODO(caprita): Remove this snippet of code, it doesn't seem to serve
	// any purpose.
	path, err := filepath.EvalSymlinks(os.Args[0])
	if err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("EvalSymlinks(%v) failed: %v", os.Args[0], err))
	}

	if err := os.MkdirAll(logs, 0711); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("MkdirAll(%v) failed: %v", logs, err))
	}
	stderrLog, stdoutLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")

	output := "#!/bin/bash\n"
	output += "if [ -z \"$DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR\" ]; then\n"
	output += fmt.Sprintf("  TIMESTAMP=$(%s)\n", DateCommand)
	output += fmt.Sprintf("  exec > %s-$TIMESTAMP 2> %s-$TIMESTAMP\n", stdoutLog, stderrLog)
	output += "  LOG_TO_STDERR=false\n"
	output += "else\n"
	output += "  LOG_TO_STDERR=true\n"
	output += "fi\n"
	output += strings.Join(config.QuoteEnv(append(envelope.Env, configSettings...)), " ") + " "
	// 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", filepath.Join(workspace, "deviced")) + " "
	output += fmt.Sprintf("--log_dir=%q ", logs)
	output += "--logtostderr=${LOG_TO_STDERR} "
	output += strings.Join(envelope.Args, " ")

	path = filepath.Join(workspace, "deviced.sh")
	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
		return verror.New(errors.ErrOperationFailed, nil, fmt.Sprintf("WriteFile(%v) failed: %v", path, err))
	}
	return nil
}

func (s *deviceService) updateDeviceManager(ctx *context.T) error {
	if len(s.config.Origin) == 0 {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	envelope, err := fetchEnvelope(ctx, s.config.Origin)
	if err != nil {
		return err
	}
	if envelope.Title != application.DeviceManagerTitle {
		return verror.New(errors.ErrAppTitleMismatch, ctx, fmt.Sprintf("app title mismatch. Got %q, expected %q.", envelope.Title, application.DeviceManagerTitle))
	}
	// Read and merge persistent args, if present.
	if args, err := loadPersistentArgs(s.config.Root); err == nil {
		envelope.Args = append(envelope.Args, args...)
	}
	if s.config.Envelope != nil && reflect.DeepEqual(envelope, s.config.Envelope) {
		return verror.New(errors.ErrUpdateNoOp, ctx)
	}
	// Create new workspace.
	workspace := filepath.Join(s.config.Root, "device-manager", generateVersionDirName())
	perm := os.FileMode(0700)
	if err := os.MkdirAll(workspace, perm); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("MkdirAll(%v, %v) failed: %v", workspace, perm, err))
	}

	deferrer := func() {
		CleanupDir(ctx, workspace, "")
	}
	defer func() {
		if deferrer != nil {
			deferrer()
		}
	}()

	// Populate the new workspace with a device manager binary.
	// TODO(caprita): match identical binaries on binary signature
	// rather than binary object name.
	sameBinary := s.config.Envelope != nil && envelope.Binary.File == s.config.Envelope.Binary.File
	if sameBinary {
		if err := LinkSelf(workspace, "deviced"); err != nil {
			return err
		}
	} else {
		if err := downloadBinary(ctx, envelope.Publisher, &envelope.Binary, workspace, "deviced"); err != nil {
			return err
		}
	}

	// Populate the new workspace with a device manager script.
	configSettings, err := s.config.Save(envelope)
	if err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, err)
	}

	logs := filepath.Join(s.config.Root, "device-manager", "logs")
	if err := GenerateScript(workspace, configSettings, envelope, logs); err != nil {
		return err
	}

	if err := s.testDeviceManager(ctx, workspace, envelope); err != nil {
		return verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("testDeviceManager failed: %v", err))
	}

	if err := UpdateLink(filepath.Join(workspace, "deviced.sh"), s.config.CurrentLink); err != nil {
		return err
	}

	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	deferrer = nil
	return nil
}

func (*deviceService) Install(ctx *context.T, _ rpc.ServerCall, _ string, _ device.Config, _ application.Packages) (string, error) {
	return "", verror.New(errors.ErrInvalidSuffix, ctx)
}

func (*deviceService) Run(ctx *context.T, _ rpc.ServerCall) error {
	return verror.New(errors.ErrInvalidSuffix, ctx)
}

func (s *deviceService) Revert(ctx *context.T, _ rpc.ServerCall) error {
	if s.config.Previous == "" {
		return verror.New(errors.ErrUpdateNoOp, ctx, fmt.Sprintf("Revert failed: no previous version"))
	}
	updatingState := s.updating
	if updatingState.testAndSetUpdating() {
		return verror.New(errors.ErrOperationInProgress, ctx, fmt.Sprintf("Revert failed: already in progress"))
	}
	err := s.revertDeviceManager(ctx)
	if err != nil {
		updatingState.unsetUpdating()
	}
	return err
}

func (*deviceService) Instantiate(ctx *context.T, _ device.ApplicationInstantiateServerCall) (string, error) {
	return "", verror.New(errors.ErrInvalidSuffix, ctx)
}

func (*deviceService) Delete(ctx *context.T, _ rpc.ServerCall) error {
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (s *deviceService) Kill(ctx *context.T, _ rpc.ServerCall, _ time.Duration) error {
	if s.restartHandler != nil {
		s.restartHandler()
	}
	v23.GetAppCycle(ctx).Stop(ctx)
	return nil
}

func (*deviceService) Uninstall(ctx *context.T, _ rpc.ServerCall) error {
	return verror.New(errors.ErrInvalidSuffix, ctx)
}

func (s *deviceService) Update(ctx *context.T, _ rpc.ServerCall) error {
	ctx, cancel := context.WithTimeout(ctx, rpcContextLongTimeout)
	defer cancel()

	updatingState := s.updating
	if updatingState.testAndSetUpdating() {
		return verror.New(errors.ErrOperationInProgress, ctx)
	}

	err := s.updateDeviceManager(ctx)
	if err != nil {
		updatingState.unsetUpdating()
	}
	return err
}

func (*deviceService) UpdateTo(*context.T, rpc.ServerCall, string) error {
	// TODO(jsimsa): Implement.
	return nil
}

func (s *deviceService) SetPermissions(_ *context.T, _ rpc.ServerCall, perms access.Permissions, version string) error {
	d := PermsDir(s.disp.config)
	return s.disp.permsStore.Set(d, perms, version)
}

func (s *deviceService) GetPermissions(*context.T, rpc.ServerCall) (perms access.Permissions, version string, err error) {
	d := PermsDir(s.disp.config)
	return s.disp.permsStore.Get(d)
}

// TODO(rjkroege): Make it possible for users on the same system to also
// associate their accounts with their identities.
func (s *deviceService) AssociateAccount(_ *context.T, _ rpc.ServerCall, identityNames []string, accountName string) error {
	if accountName == "" {
		return s.uat.DisassociateSystemAccountForBlessings(identityNames)
	}
	// TODO(rjkroege): Optionally verify here that the required uname is a valid.
	return s.uat.AssociateSystemAccountForBlessings(identityNames, accountName)
}

func (s *deviceService) ListAssociations(ctx *context.T, call rpc.ServerCall) (associations []device.Association, err error) {
	// Temporary code. Dump this.
	if ctx.V(2) {
		b, r := security.RemoteBlessingNames(ctx, call.Security())
		ctx.Infof("ListAssociations given blessings: %v\n", b)
		if len(r) > 0 {
			ctx.Infof("ListAssociations rejected blessings: %v\n", r)
		}
	}
	return s.uat.AllBlessingSystemAssociations()
}

func (*deviceService) Debug(*context.T, rpc.ServerCall) (string, error) {
	return "Not implemented", nil
}

func (s *deviceService) Status(*context.T, rpc.ServerCall) (device.Status, error) {
	state := device.InstanceStateRunning
	if s.updating.updating {
		state = device.InstanceStateUpdating
	}
	// Extract the version from the current link path.
	//
	// TODO(caprita): make the version available in the device's directory.
	scriptPath, err := filepath.EvalSymlinks(s.config.CurrentLink)
	if err != nil {
		return nil, err
	}
	dir := filepath.Dir(scriptPath)
	versionDir := filepath.Base(dir)
	if versionDir == "." {
		versionDir = "base"
	}
	return device.StatusDevice{Value: device.DeviceStatus{
		State:   state,
		Version: versionDir,
	}}, nil
}

func (s *deviceService) TidyNow(ctx *context.T, _ rpc.ServerCall) error {
	ec := make(chan error)
	s.tidying <- tidyRequests{ctx: ctx, bc: ec}
	return <-ec
}
