// Package modules provides a mechanism for running commonly used services
// as subprocesses and client functionality for accessing those services.
// Such services and functions are collectively called 'commands' and are
// registered with and executed within a context, defined by the Shell type.
// The Shell is analagous to the original UNIX shell and maintains a
// key, value store of variables that is accessible to all of the commands that
// it hosts. These variables may be referenced by the arguments passed to
// commands.
//
// Commands are added to a shell in two ways: one for a subprocess and another
// for an inprocess function.
//
// - subprocesses are added using the AddSubprocess method in the parent
//   and by the modules.RegisterChild function in the child process (typically
//   RegisterChild is called from an init function). modules.Dispatch must
//   be called in the child process to execute the subprocess 'Main' function
//   provided to RegisterChild.
// - inprocess functions are added using the AddFunction method.
//
// In all cases commands are started by invoking the Start method on the
// Shell with the name of the command to run. An instance of the Handle
// interface is returned which can be used to interact with the function
// or subprocess, and in particular to read/write data from/to it using io
// channels that follow the stdin, stdout, stderr convention.
//
// A simple protocol must be followed by all commands, namely, they
// should wait for their stdin stream to be closed before exiting. The
// caller can then coordinate with any command by writing to that stdin
// stream and reading responses from the stdout stream, and it can close
// stdin when it's ready for the command to exit.
//
// The signature of the function that implements the command is the
// same for both types of command and is defined by the Main function type.
// In particular stdin, stdout and stderr are provided as parameters, as is
// a map representation of the shell's environment.
package modules

import (
	"bufio"
	"fmt"
	"io"
	"strings"
	"sync"

	"veyron2/vlog"
)

// Shell represents the context within which commands are run.
type Shell struct {
	mu      sync.Mutex
	env     map[string]string
	cmds    map[string]*commandDesc
	handles map[Handle]struct{}
}

type commandDesc struct {
	factory func() command
	help    string
}

type childRegistrar struct {
	sync.Mutex
	mains map[string]Main
}

var child = &childRegistrar{mains: make(map[string]Main)}

// NewShell creates a new instance of Shell.
func NewShell() *Shell {
	return &Shell{
		env:     make(map[string]string),
		cmds:    make(map[string]*commandDesc),
		handles: make(map[Handle]struct{}),
	}
}

type Main func(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error

// AddSubprocess adds a new command to the Shell that will be run
// as a subprocess. In addition, the child process must call RegisterChild
// using the same name used here and provide the function to be executed
// in the child.
func (sh *Shell) AddSubprocess(name string, help string) {
	if !child.hasCommand(name) {
		vlog.Infof("Warning: %q is not registered with modules.Dispatcher", name)
	}
	entryPoint := shellEntryPoint + "=" + name
	sh.mu.Lock()
	sh.cmds[name] = &commandDesc{func() command { return newExecHandle(entryPoint) }, help}
	sh.mu.Unlock()
}

// AddFunction adds a new command to the Shell that will be run
// within the current process.
func (sh *Shell) AddFunction(name string, main Main, help string) {
	sh.mu.Lock()
	sh.cmds[name] = &commandDesc{func() command { return newFunctionHandle(main) }, help}
	sh.mu.Unlock()
}

// String returns a string representation of the Shell, which is a
// concatenation of the help messages of each Command currently available
// to it.
func (sh *Shell) String() string {
	sh.mu.Lock()
	defer sh.mu.Unlock()
	h := ""
	for n, _ := range sh.cmds {
		h += n + ", "
	}
	return strings.TrimRight(h, ", ")
}

// Help returns the help message for the specified command.
func (sh *Shell) Help(command string) string {
	sh.mu.Lock()
	defer sh.mu.Unlock()
	if c := sh.cmds[command]; c != nil {
		return command + ": " + c.help
	}
	return ""
}

// Start starts the specified command, it returns a Handle which can be used
// for interacting with that command. The Shell tracks all of the Handles
// that it creates so that it can shut them down when asked to. If any
// application calls Shutdown on a handle directly, it must call the Forget
// method on the Shell instance hosting that Handle to avoid storage leaks.
func (sh *Shell) Start(command string, args ...string) (Handle, error) {
	sh.mu.Lock()
	cmd := sh.cmds[command]
	if cmd == nil {
		sh.mu.Unlock()
		return nil, fmt.Errorf("command %q is not available", command)
	}
	expanded := sh.expand(args...)
	sh.mu.Unlock()
	h, err := cmd.factory().start(sh, expanded...)
	if err != nil {
		return nil, err
	}
	sh.mu.Lock()
	sh.handles[h] = struct{}{}
	sh.mu.Unlock()
	return h, nil
}

// Forget tells the Shell to stop tracking the supplied Handle.
func (sh *Shell) Forget(h Handle) {
	sh.mu.Lock()
	delete(sh.handles, h)
	sh.mu.Unlock()
}

func (sh *Shell) expand(args ...string) []string {
	exp := []string{}
	for _, a := range args {
		if len(a) > 0 && a[0] == '$' {
			if v, present := sh.env[a[1:]]; present {
				exp = append(exp, v)
				continue
			}
		}
		exp = append(exp, a)
	}
	return exp
}

// GetVar returns the variable associated with the specified key
// and an indication of whether it is defined or not.
func (sh *Shell) GetVar(key string) (string, bool) {
	sh.mu.Lock()
	defer sh.mu.Unlock()
	v, present := sh.env[key]
	return v, present
}

// SetVar sets the value to be associated with key.
func (sh *Shell) SetVar(key, value string) {
	sh.mu.Lock()
	defer sh.mu.Unlock()
	// TODO(cnicolaou): expand value
	sh.env[key] = value
}

// Env returns the entire set of environment variables associated with this
// Shell as a string slice.
func (sh *Shell) Env() []string {
	vars := []string{}
	sh.mu.Lock()
	defer sh.mu.Unlock()
	for k, v := range sh.env {
		vars = append(vars, k+"="+v)
	}
	return vars
}

// Cleanup calls Shutdown on all of the Handles currently being tracked
// by the Shell. Any buffered output from the command's stderr stream
// will be written to the supplied io.Writer. If the io.Writer is nil
// then any such output is lost.
func (sh *Shell) Cleanup(output io.Writer) {
	sh.mu.Lock()
	defer sh.mu.Unlock()
	for k, _ := range sh.handles {
		k.Shutdown(output)
	}
	sh.handles = make(map[Handle]struct{})
}

// Handle represents a running command.
type Handle interface {
	// Stdout returns a buffered reader to the running command's stdout stream.
	Stdout() *bufio.Reader

	// Stderr returns an unbuffered reader to the running command's stderr
	// stream.
	Stderr() io.Reader

	// Stdin returns a writer to the running command's stdin. The
	// convention is for commands to wait for stdin to be closed before
	// they exit, thus the caller should close stdin when it wants the
	// command to exit cleanly.
	Stdin() io.WriteCloser

	// Shutdown closes the Stdin for the command. It is primarily intended
	// for being called by the Shell, if other application code calls it
	// then it should use the Shell's Forget method to have the Shell stop
	// tracking the handle. Any buffered stderr output from the command will
	// be written to the supplied io.Writer. If the io.Writer is nil then
	// any such output is lost.
	Shutdown(io.Writer)
}

// command is used to abstract the implementations of inprocess and subprocess
// commands.
type command interface {
	start(sh *Shell, args ...string) (Handle, error)
}

func WaitForEOF(stdin io.Reader) {
	buf := [1024]byte{}
	for {
		if _, err := stdin.Read(buf[:]); err == io.EOF {
			return
		}
	}
}
