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

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"testing"
	"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/services/repository"
	"v.io/x/lib/vlog"

	"v.io/x/ref/services/internal/binarylib"
	"v.io/x/ref/services/internal/packages"
)

type mockDeviceInvoker struct {
	tape *tape
	t    *testing.T
}

// Mock ListAssociations
type ListAssociationResponse struct {
	na  []device.Association
	err error
}

func (mdi *mockDeviceInvoker) ListAssociations(*context.T, rpc.ServerCall) (associations []device.Association, err error) {
	vlog.VI(2).Infof("ListAssociations() was called")

	ir := mdi.tape.Record("ListAssociations")
	r := ir.(ListAssociationResponse)
	return r.na, r.err
}

// Mock AssociateAccount
type AddAssociationStimulus struct {
	fun           string
	identityNames []string
	accountName   string
}

// simpleCore implements the core of all mock methods that take
// arguments and return error.
func (mdi *mockDeviceInvoker) simpleCore(callRecord interface{}, name string) error {
	ri := mdi.tape.Record(callRecord)
	switch r := ri.(type) {
	case nil:
		return nil
	case error:
		return r
	}
	log.Fatalf("%s (mock) response %v is of bad type", name, ri)
	return nil
}

func (mdi *mockDeviceInvoker) AssociateAccount(_ *context.T, _ rpc.ServerCall, identityNames []string, accountName string) error {
	return mdi.simpleCore(AddAssociationStimulus{"AssociateAccount", identityNames, accountName}, "AssociateAccount")
}

func (mdi *mockDeviceInvoker) Claim(_ *context.T, _ rpc.ServerCall, pairingToken string) error {
	return mdi.simpleCore("Claim", "Claim")
}

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

func (*mockDeviceInvoker) IsRunnable(_ *context.T, _ rpc.ServerCall, description binary.Description) (bool, error) {
	return false, nil
}

func (*mockDeviceInvoker) Reset(_ *context.T, _ rpc.ServerCall, deadline uint64) error { return nil }

// Mock Install
type InstallStimulus struct {
	fun      string
	appName  string
	config   device.Config
	packages application.Packages
	envelope application.Envelope
	// files holds a map from file  or package name to file or package size.
	// The app binary  has the key "binary". Each of  the packages will have
	// the key "package/<package name>". The override packages will have the
	// key "overridepackage/<package name>".
	files map[string]int64
}

type InstallResponse struct {
	appId string
	err   error
}

const (
	// If provided with this app name, the mock device manager skips trying
	// to fetch the envelope from the name.
	appNameNoFetch = "skip-envelope-fetching"
	// If provided with a fetcheable app name, the mock device manager sets
	// the app name in the stimulus to this constant.
	appNameAfterFetch = "envelope-fetched"
	// The mock device manager sets the binary name in the envelope in the
	// stimulus to this constant.
	binaryNameAfterFetch = "binary-fetched"
)

func packageSize(pkgPath string) int64 {
	info, err := os.Stat(pkgPath)
	if err != nil {
		return -1
	}
	if info.IsDir() {
		infos, err := ioutil.ReadDir(pkgPath)
		if err != nil {
			return -1
		}
		var size int64
		for _, i := range infos {
			size += i.Size()
		}
		return size
	} else {
		return info.Size()
	}
}

func fetchPackageSize(ctx *context.T, pkgVON string) (int64, error) {
	dir, err := ioutil.TempDir("", "package")
	if err != nil {
		return 0, fmt.Errorf("failed to create temp package dir: %v", err)
	}
	defer os.RemoveAll(dir)
	tmpFile := filepath.Join(dir, "downloaded")
	if err := binarylib.DownloadToFile(ctx, pkgVON, tmpFile); err != nil {
		return 0, fmt.Errorf("DownloadToFile failed: %v", err)
	}
	dst := filepath.Join(dir, "install")
	if err := packages.Install(tmpFile, dst); err != nil {
		return 0, fmt.Errorf("packages.Install failed: %v", err)
	}
	return packageSize(dst), nil
}

func (mdi *mockDeviceInvoker) Install(ctx *context.T, _ rpc.ServerCall, appName string, config device.Config, packages application.Packages) (string, error) {
	is := InstallStimulus{"Install", appName, config, packages, application.Envelope{}, nil}
	if appName != appNameNoFetch {
		// Fetch the envelope and record it in the stimulus.
		envelope, err := repository.ApplicationClient(appName).Match(ctx, []string{"test"})
		if err != nil {
			return "", err
		}
		binaryName := envelope.Binary.File
		envelope.Binary.File = binaryNameAfterFetch
		is.appName = appNameAfterFetch
		is.files = make(map[string]int64)
		// Fetch the binary and record its size in the stimulus.
		data, mediaInfo, err := binarylib.Download(ctx, binaryName)
		if err != nil {
			return "", err
		}
		is.files["binary"] = int64(len(data))
		if mediaInfo.Type != "application/octet-stream" {
			return "", fmt.Errorf("unexpected media type: %v", mediaInfo)
		}
		// Iterate over the packages, download them, compute the size of
		// the file(s) that make up each package, and record that in the
		// stimulus.
		for pkgLocalName, pkgVON := range envelope.Packages {
			size, err := fetchPackageSize(ctx, pkgVON.File)
			if err != nil {
				return "", err
			}
			is.files[naming.Join("packages", pkgLocalName)] = size
		}
		envelope.Packages = nil
		for pkgLocalName, pkg := range packages {
			size, err := fetchPackageSize(ctx, pkg.File)
			if err != nil {
				return "", err
			}
			is.files[naming.Join("overridepackages", pkgLocalName)] = size
		}
		is.packages = nil
		is.envelope = envelope
	}
	r := mdi.tape.Record(is).(InstallResponse)
	return r.appId, r.err
}

func (mdi *mockDeviceInvoker) Run(*context.T, rpc.ServerCall) error {
	return mdi.simpleCore("Run", "Run")
}

func (i *mockDeviceInvoker) Revert(*context.T, rpc.ServerCall) error { return nil }

type InstantiateResponse struct {
	err        error
	instanceID string
}

func (mdi *mockDeviceInvoker) Instantiate(*context.T, rpc.StreamServerCall) (string, error) {
	ir := mdi.tape.Record("Instantiate")
	r := ir.(InstantiateResponse)
	return r.instanceID, r.err
}

type KillStimulus struct {
	fun   string
	delta time.Duration
}

func (mdi *mockDeviceInvoker) Kill(_ *context.T, _ rpc.ServerCall, delta time.Duration) error {
	return mdi.simpleCore(KillStimulus{"Kill", delta}, "Kill")
}

func (mdi *mockDeviceInvoker) Delete(*context.T, rpc.ServerCall) error {
	return mdi.simpleCore("Delete", "Delete")
}

func (*mockDeviceInvoker) Uninstall(*context.T, rpc.ServerCall) error { return nil }

func (i *mockDeviceInvoker) Update(*context.T, rpc.ServerCall) error { return nil }

func (*mockDeviceInvoker) UpdateTo(*context.T, rpc.ServerCall, string) error { return nil }

// Mock Permissions getting and setting
type GetPermissionsResponse struct {
	perms   access.Permissions
	version string
	err     error
}

type SetPermissionsStimulus struct {
	fun     string
	perms   access.Permissions
	version string
}

func (mdi *mockDeviceInvoker) SetPermissions(_ *context.T, _ rpc.ServerCall, perms access.Permissions, version string) error {
	return mdi.simpleCore(SetPermissionsStimulus{"SetPermissions", perms, version}, "SetPermissions")
}

func (mdi *mockDeviceInvoker) GetPermissions(*context.T, rpc.ServerCall) (access.Permissions, string, error) {
	ir := mdi.tape.Record("GetPermissions")
	r := ir.(GetPermissionsResponse)
	return r.perms, r.version, r.err
}

func (mdi *mockDeviceInvoker) Debug(*context.T, rpc.ServerCall) (string, error) {
	ir := mdi.tape.Record("Debug")
	r := ir.(string)
	return r, nil
}

func (mdi *mockDeviceInvoker) Status(*context.T, rpc.ServerCall) (device.Status, error) {
	ir := mdi.tape.Record("Status")
	r := ir.(device.Status)
	return r, nil
}

type GlobStimulus struct {
	pattern string
}

type GlobResponse struct {
	results []string
}

func (mdi *mockDeviceInvoker) Glob__(_ *context.T, _ rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) {
	gs := GlobStimulus{pattern}
	gr := mdi.tape.Record(gs).(GlobResponse)
	ch := make(chan naming.GlobReply, len(gr.results))
	defer close(ch)
	for _, r := range gr.results {
		ch <- naming.GlobReplyEntry{naming.MountEntry{Name: r}}
	}
	return ch, nil
}

type dispatcher struct {
	tapes *tapeMap
	t     *testing.T
}

func newDispatcher(t *testing.T, tapes *tapeMap) rpc.Dispatcher {
	return &dispatcher{tapes: tapes, t: t}
}

func (d *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
	return &mockDeviceInvoker{tape: d.tapes.forSuffix(suffix), t: d.t}, nil, nil
}

func startServer(t *testing.T, ctx *context.T, tapes *tapeMap) (rpc.Server, naming.Endpoint, error) {
	dispatcher := newDispatcher(t, tapes)
	server, err := v23.NewServer(ctx)
	if err != nil {
		t.Errorf("NewServer failed: %v", err)
		return nil, nil, err
	}
	endpoints, err := server.Listen(v23.GetListenSpec(ctx))
	if err != nil {
		t.Errorf("Listen failed: %v", err)
		stopServer(t, server)
		return nil, nil, err
	}
	if err := server.ServeDispatcher("", dispatcher); err != nil {
		t.Errorf("ServeDispatcher failed: %v", err)
		stopServer(t, server)
		return nil, nil, err
	}
	return server, endpoints[0], nil
}

func stopServer(t *testing.T, server rpc.Server) {
	if err := server.Stop(); err != nil {
		t.Errorf("server.Stop failed: %v", err)
	}
}
