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

import (
	"flag"
	"io"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"time"

	"v.io/v23/verror"
	"v.io/x/lib/vlog"
	vexec "v.io/x/ref/lib/exec"
	"v.io/x/ref/lib/mgmt"
	"v.io/x/ref/test/expect"
)

// execHandle implements both the command and Handle interfaces.
type execHandle struct {
	*expect.Session
	mu         sync.Mutex
	cmd        *exec.Cmd
	name       string
	entryPoint string
	handle     *vexec.ParentHandle
	sh         *Shell
	stderr     *os.File
	stdout     io.ReadCloser
	stdin      io.WriteCloser
	procErrCh  chan error
	opts       *StartOpts
}

func testFlags() []string {
	var fl []string
	// pass logging flags to any subprocesses
	for fname, fval := range vlog.Log.ExplicitlySetFlags() {
		fl = append(fl, "--"+fname+"="+fval)
	}
	timeout := flag.Lookup("test.timeout")
	if timeout == nil {
		// not a go test binary
		return fl
	}
	// must be a go test binary
	val := timeout.Value.(flag.Getter).Get().(time.Duration)
	if val.String() != timeout.DefValue {
		// use supplied command value for subprocesses
		fl = append(fl, "--test.timeout="+timeout.Value.String())
	} else {
		// translate default value into 3m for subproccesses.  The
		// default of 10m is too long to wait in order to find out that
		// our subprocess is wedged.
		fl = append(fl, "--test.timeout=3m")
	}
	return fl
}

func newExecHandle(name string) command {
	return &execHandle{name: name, entryPoint: shellEntryPoint + "=" + name, procErrCh: make(chan error, 1)}
}

func newExecHandleForExternalCommand(name string) command {
	return &execHandle{name: name, procErrCh: make(chan error, 1)}
}

func (eh *execHandle) Stdout() io.Reader {
	eh.mu.Lock()
	defer eh.mu.Unlock()
	return eh.stdout
}

func (eh *execHandle) Stderr() io.Reader {
	eh.mu.Lock()
	defer eh.mu.Unlock()
	return eh.stderr
}

func (eh *execHandle) Stdin() io.Writer {
	eh.mu.Lock()
	defer eh.mu.Unlock()
	return eh.stdin
}

func (eh *execHandle) CloseStdin() {
	eh.mu.Lock()
	eh.stdin.Close()
	eh.mu.Unlock()
}

func (eh *execHandle) envelope(sh *Shell, env []string, args ...string) ([]string, []string) {
	newargs := []string{os.Args[0]}
	newargs = append(newargs, testFlags()...)
	newargs = append(newargs, args...)
	// Be careful to remove any existing shellEntryPoint env vars. This
	// can happen when subprocesses run other subprocesses etc.
	cleaned := make([]string, 0, len(env)+1)
	for _, e := range env {
		if strings.HasPrefix(e, shellEntryPoint+"=") {
			continue
		}
		cleaned = append(cleaned, e)
	}
	return newargs, append(cleaned, eh.entryPoint)
}

func (eh *execHandle) start(sh *Shell, agentfd *os.File, opts *StartOpts, env []string, args ...string) (Handle, error) {
	eh.mu.Lock()
	defer eh.mu.Unlock()
	eh.sh = sh
	eh.opts = opts
	cmdPath := args[0]
	newargs, newenv := args, env

	// If an entry point is specified, use the envelope execution environment.
	if len(eh.entryPoint) > 0 {
		cmdPath = os.Args[0]
		newargs, newenv = eh.envelope(sh, env, args[1:]...)
	}

	cmd := exec.Command(cmdPath, newargs[1:]...)
	cmd.Env = newenv

	stderr, err := newLogfile("stderr", eh.name)
	if err != nil {
		return nil, err
	}
	cmd.Stderr = stderr
	// We use a custom queue-based Writer implementation for stdout to
	// decouple the consumers of eh.stdout from the file where the child
	// sends its output.  This avoids data races between closing the file
	// and reading from it (since cmd.Wait will wait for the all readers to
	// be done before closing it).  It also enables Shutdown to drain stdout
	// while respecting the timeout.
	stdout := newRW()
	cmd.Stdout = stdout

	// If we have an explicit stdin to pass to the child, use that,
	// otherwise create a pipe and return the write side of that pipe
	// in the handle.
	if eh.opts.Stdin != nil {
		cmd.Stdin = eh.opts.Stdin
	} else {
		stdin, err := cmd.StdinPipe()
		if err != nil {
			return nil, err
		}
		eh.stdin = stdin
	}
	config := vexec.NewConfig()

	execOpts := []vexec.ParentHandleOpt{}
	if !eh.opts.ExecProtocol {
		execOpts = append(execOpts, vexec.UseExecProtocolOpt(false))
	} else {
		serialized, err := sh.config.Serialize()
		if err != nil {
			return nil, err
		}
		config.MergeFrom(serialized)
		if agentfd != nil {
			childfd := len(cmd.ExtraFiles) + vexec.FileOffset
			config.Set(mgmt.SecurityAgentFDConfigKey, strconv.Itoa(childfd))
			cmd.ExtraFiles = append(cmd.ExtraFiles, agentfd)
			defer agentfd.Close()
		}
		execOpts = append(execOpts, vexec.ConfigOpt{Config: config})
	}

	// TODO(cnicolaou): for external commands, vexec should either not be
	// used or it should taken an option to not use its protocol, and in
	// particular to share secrets with children.
	handle := vexec.NewParentHandle(cmd, execOpts...)
	eh.stdout = stdout
	eh.stderr = stderr
	eh.handle = handle
	eh.cmd = cmd
	vlog.VI(1).Infof("Start: %q stderr: %s", eh.name, stderr.Name())
	vlog.VI(1).Infof("Start: %q args: %v", eh.name, cmd.Args)
	vlog.VI(2).Infof("Start: %q env: %v", eh.name, cmd.Env)
	if err := handle.Start(); err != nil {
		// The child process failed to start, either because of some setup
		// error (e.g. creating pipes for it to use), or a bad binary etc.
		// A handle is returned, so that Shutdown etc may be called, hence
		// the error must be sent over eh.procErrCh to allow Shutdown to
		// terminate.
		eh.procErrCh <- err
		return eh, err
	}
	if eh.opts.ExecProtocol {
		if err := eh.handle.WaitForReady(eh.opts.StartTimeout); err != nil {
			// The child failed to call SetReady, most likely because of bad
			// command line arguments or some other early exit in the child
			// process.
			// As per Start above, a handle is returned and the error
			// sent over eh.procErrCh.
			eh.procErrCh <- err
			return eh, err
		}
	}
	vlog.VI(1).Infof("Started: %q, pid %d", eh.name, cmd.Process.Pid)
	go func() {
		eh.procErrCh <- eh.handle.Wait(0)
		// It's now safe to close eh.stdout, since Wait only returns
		// once all writes from the pipe to the stdout Writer have
		// completed.  Closing eh.stdout lets consumers of stdout wrap
		// up (they'll receive EOF).
		eh.stdout.Close()
	}()
	eh.Session = expect.NewSession(opts.ExpectTesting, stdout, opts.ExpectTimeout)
	eh.Session.SetVerbosity(eh.sh.sessionVerbosity)
	return eh, nil
}

func (eh *execHandle) Pid() int {
	return eh.cmd.Process.Pid
}

func (eh *execHandle) Shutdown(stdout, stderr io.Writer) error {
	eh.mu.Lock()
	defer eh.mu.Unlock()
	vlog.VI(1).Infof("Shutdown: %q", eh.name)
	defer vlog.VI(1).Infof("Shutdown: %q [DONE]", eh.name)
	if eh.stdin != nil {
		eh.stdin.Close()
	}
	defer eh.sh.Forget(eh)

	waitStdout := make(chan struct{})
	if stdout != nil {
		// Drain stdout.
		go func() {
			io.Copy(stdout, eh.stdout)
			close(waitStdout)
		}()
	} else {
		close(waitStdout)
	}

	var procErr error
	select {
	case procErr = <-eh.procErrCh:
		// The child has exited already.
	case <-time.After(eh.opts.ShutdownTimeout):
		// Time out waiting for child to exit.
		procErr = verror.New(vexec.ErrTimeout, nil)
		// Force close stdout to unblock any readers of stdout
		// (including the drain loop started above).
		eh.stdout.Close()
	}
	<-waitStdout

	// Transcribe stderr.
	outputFromFile(eh.stderr, stderr)
	os.Remove(eh.stderr.Name())

	return procErr
}
