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

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"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/services/repository"
	"v.io/v23/uniqueid"
	"v.io/x/lib/vlog"

	"v.io/x/lib/cmdline"
	"v.io/x/ref/lib/v23cmd"
	"v.io/x/ref/services/internal/packages"
)

var cmdInstallLocal = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runInstallLocal),
	Name:     "install-local",
	Short:    "Install the given application from the local system.",
	Long:     "Install the given application specified using a local path, and print the name of the new installation.",
	ArgsName: "<device> <title> [ENV=VAL ...] binary [--flag=val ...] [PACKAGES path ...]",
	ArgsLong: `
<device> is the vanadium object name of the device manager's app service.

<title> is the app title.

This is followed by an arbitrary number of environment variable settings, the
local path for the binary to install, and arbitrary flag settings and args.
Optionally, this can be followed by 'PACKAGES' and a list of local files and
directories to be installed as packages for the app`}

func init() {
	cmdInstallLocal.Flags.Var(&configOverride, "config", "JSON-encoded device.Config object, of the form: '{\"flag1\":\"value1\",\"flag2\":\"value2\"}'")
	cmdInstallLocal.Flags.Var(&packagesOverride, "packages", "JSON-encoded application.Packages object, of the form: '{\"pkg1\":{\"File\":\"local file path1\"},\"pkg2\":{\"File\":\"local file path 2\"}}'")
}

type mapDispatcher map[string]interface{}

func (d mapDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
	o, ok := d[suffix]
	if !ok {
		return nil, nil, fmt.Errorf("suffix %s not found", suffix)
	}
	// TODO(caprita): Do not allow everyone, even for a short-lived server.
	return o, security.AllowEveryone(), nil
}

type mapServer struct {
	name       string
	dispatcher mapDispatcher
}

func (ms *mapServer) serve(name string, object interface{}) (string, error) {
	if _, ok := ms.dispatcher[name]; ok {
		return "", fmt.Errorf("can't have more than one object with name %v", name)
	}
	ms.dispatcher[name] = object
	return naming.Join(ms.name, name), nil
}

func createServer(ctx *context.T, stderr io.Writer) (*mapServer, func(), error) {
	server, err := v23.NewServer(ctx)
	if err != nil {
		return nil, nil, err
	}
	spec := v23.GetListenSpec(ctx)
	var name string
	if spec.Proxy != "" {
		id, err := uniqueid.Random()
		if err != nil {
			return nil, nil, err
		}
		name = id.String()
		// Disable listening on local addresses to avoid publishing
		// local endpoints to the mount table.  The only thing published
		// should be the proxied endpoint.
		spec.Addrs = nil
	}
	endpoints, err := server.Listen(spec)
	if err != nil {
		return nil, nil, err
	}
	dispatcher := make(mapDispatcher)
	if err := server.ServeDispatcher(name, dispatcher); err != nil {
		return nil, nil, err
	}
	vlog.VI(1).Infof("Server listening on %v (%v)", endpoints, name)
	cleanup := func() {
		if err := server.Stop(); err != nil {
			fmt.Fprintf(stderr, "server.Stop failed: %v", err)
		}
	}
	if name != "" {
		// Send a name rooted in our namespace root rather than the
		// relative name (in case the device manager uses a different
		// namespace root).
		//
		// TODO(caprita): Avoid relying on a mounttable altogether, and
		// instead pull out the proxied address and just send that.
		nsRoots := v23.GetNamespace(ctx).Roots()
		if len(nsRoots) > 0 {
			name = naming.Join(nsRoots[0], name)
		}
	} else if len(endpoints) > 0 {
		name = endpoints[0].Name()
	} else {
		return nil, nil, fmt.Errorf("no endpoints")
	}
	return &mapServer{name: name, dispatcher: dispatcher}, cleanup, nil
}

var errNotImplemented = fmt.Errorf("method not implemented")

type binaryInvoker string

func (binaryInvoker) Create(*context.T, rpc.ServerCall, int32, repository.MediaInfo) error {
	return errNotImplemented
}

func (binaryInvoker) Delete(*context.T, rpc.ServerCall) error {
	return errNotImplemented
}

func (i binaryInvoker) Download(_ *context.T, call repository.BinaryDownloadServerCall, _ int32) error {
	fileName := string(i)
	fStat, err := os.Stat(fileName)
	if err != nil {
		return err
	}
	vlog.VI(1).Infof("Download commenced for %v (%v bytes)", fileName, fStat.Size())
	file, err := os.Open(fileName)
	if err != nil {
		return err
	}
	defer file.Close()
	bufferLength := 4096
	buffer := make([]byte, bufferLength)
	sender := call.SendStream()
	var sentTotal int64
	const logChunk = 1 << 20
	for {
		n, err := file.Read(buffer)
		switch err {
		case io.EOF:
			vlog.VI(1).Infof("Download complete for %v (%v bytes)", fileName, fStat.Size())
			return nil
		case nil:
			if err := sender.Send(buffer[:n]); err != nil {
				return err
			}
			if sentTotal/logChunk < (sentTotal+int64(n))/logChunk {
				vlog.VI(1).Infof("Download progress for %v: %v/%v", fileName, sentTotal+int64(n), fStat.Size())
			}
			sentTotal += int64(n)
		default:
			return err
		}
	}
}

func (binaryInvoker) DownloadUrl(*context.T, rpc.ServerCall) (string, int64, error) {
	return "", 0, errNotImplemented
}

func (i binaryInvoker) Stat(*context.T, rpc.ServerCall) ([]binary.PartInfo, repository.MediaInfo, error) {
	fileName := string(i)
	h := md5.New()
	bytes, err := ioutil.ReadFile(fileName)
	if err != nil {
		return []binary.PartInfo{}, repository.MediaInfo{}, err
	}
	h.Write(bytes)
	part := binary.PartInfo{Checksum: hex.EncodeToString(h.Sum(nil)), Size: int64(len(bytes))}
	return []binary.PartInfo{part}, packages.MediaInfoForFileName(fileName), nil
}

func (binaryInvoker) Upload(*context.T, repository.BinaryUploadServerCall, int32) error {
	return errNotImplemented
}

func (binaryInvoker) GetPermissions(*context.T, rpc.ServerCall) (perms access.Permissions, version string, err error) {
	return nil, "", errNotImplemented
}

func (binaryInvoker) SetPermissions(_ *context.T, _ rpc.ServerCall, perms access.Permissions, version string) error {
	return errNotImplemented
}

type envelopeInvoker application.Envelope

func (i envelopeInvoker) Match(*context.T, rpc.ServerCall, []string) (application.Envelope, error) {
	return application.Envelope(i), nil
}

func (envelopeInvoker) GetPermissions(*context.T, rpc.ServerCall) (perms access.Permissions, version string, err error) {
	return nil, "", errNotImplemented
}

func (envelopeInvoker) SetPermissions(*context.T, rpc.ServerCall, access.Permissions, string) error {
	return errNotImplemented
}

func servePackage(p string, ms *mapServer, tmpZipDir string) (string, string, error) {
	info, err := os.Stat(p)
	if os.IsNotExist(err) {
		return "", "", fmt.Errorf("%v not found: %v", p, err)
	} else if err != nil {
		return "", "", fmt.Errorf("Stat(%v) failed: %v", p, err)
	}
	pkgName := naming.Join("packages", info.Name())
	fileName := p
	// Directory packages first get zip'ped.
	if info.IsDir() {
		fileName = filepath.Join(tmpZipDir, info.Name()+".zip")
		if err := packages.CreateZip(fileName, p); err != nil {
			return "", "", err
		}
	}
	name, err := ms.serve(pkgName, repository.BinaryServer(binaryInvoker(fileName)))
	return info.Name(), name, err
}

// runInstallLocal creates a new envelope on the fly from the provided
// arguments, and then points the device manager back to itself for downloading
// the app envelope and binary.
//
// It sets up an app and binary server that only lives for the duration of the
// command, and listens on the profile's listen spec.  The caller should set the
// --v23.proxy if the machine running the command is not accessible from the
// device manager.
//
// TODO(caprita/ashankar): We should use bi-directional streams to get this
// working over the same connection that the command makes to the device
// manager.
func runInstallLocal(ctx *context.T, env *cmdline.Env, args []string) error {
	if expectedMin, got := 2, len(args); got < expectedMin {
		return env.UsageErrorf("install-local: incorrect number of arguments, expected at least %d, got %d", expectedMin, got)
	}
	deviceName, title := args[0], args[1]
	args = args[2:]
	envelope := application.Envelope{Title: title}
	// Extract the environment settings, binary, and arguments.
	firstNonEnv := len(args)
	for i, arg := range args {
		if strings.Index(arg, "=") <= 0 {
			firstNonEnv = i
			break
		}
	}
	envelope.Env = args[:firstNonEnv]
	args = args[firstNonEnv:]
	if len(args) == 0 {
		return env.UsageErrorf("install-local: missing binary")
	}
	binary := args[0]
	args = args[1:]
	firstNonArg, firstPackage := len(args), len(args)
	for i, arg := range args {
		if arg == "PACKAGES" {
			firstNonArg = i
			firstPackage = i + 1
			break
		}
	}
	envelope.Args = args[:firstNonArg]
	pkgs := args[firstPackage:]
	if _, err := os.Stat(binary); err != nil {
		return fmt.Errorf("binary %v not found: %v", binary, err)
	}
	server, cancel, err := createServer(ctx, env.Stderr)
	if err != nil {
		return fmt.Errorf("failed to create server: %v", err)
	}
	defer cancel()
	envelope.Binary.File, err = server.serve("binary", repository.BinaryServer(binaryInvoker(binary)))
	if err != nil {
		return err
	}
	vlog.VI(1).Infof("binary %v serving as %v", binary, envelope.Binary.File)

	// For each package dir/file specified in the arguments list, set up an
	// object in the binary service to serve that package, and add the
	// object name to the envelope's Packages map.
	tmpZipDir, err := ioutil.TempDir("", "packages")
	if err != nil {
		return fmt.Errorf("failed to create a temp dir for zip packages: %v", err)
	}
	defer os.RemoveAll(tmpZipDir)
	for _, p := range pkgs {
		if envelope.Packages == nil {
			envelope.Packages = make(application.Packages)
		}
		pname, oname, err := servePackage(p, server, tmpZipDir)
		if err != nil {
			return err
		}
		vlog.VI(1).Infof("package %v serving as %v", pname, oname)
		envelope.Packages[pname] = application.SignedFile{File: oname}
	}
	packagesRewritten := application.Packages{}
	for pname, pspec := range packagesOverride {
		_, oname, err := servePackage(pspec.File, server, tmpZipDir)
		if err != nil {
			return err
		}
		vlog.VI(1).Infof("package %v serving as %v", pname, oname)
		pspec.File = oname
		packagesRewritten[pname] = pspec
	}
	appName, err := server.serve("application", repository.ApplicationServer(envelopeInvoker(envelope)))
	if err != nil {
		return err
	}
	vlog.VI(1).Infof("application serving envelope as %v", appName)
	appID, err := device.ApplicationClient(deviceName).Install(ctx, appName, device.Config(configOverride), packagesRewritten)
	// Reset the value for any future invocations of "install" or
	// "install-local" (we run more than one command per process in unit
	// tests).
	configOverride = configFlag{}
	packagesOverride = packagesFlag{}
	if err != nil {
		return fmt.Errorf("Install failed: %v", err)
	}
	fmt.Fprintf(env.Stdout, "%s\n", naming.Join(deviceName, appID))
	return nil
}
