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

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"testing"

	"v.io/v23"
	"v.io/v23/context"
	"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/repository"
	"v.io/v23/verror"
)

const MockBinaryRepoName = "br"
const MockApplicationRepoName = "ar"

func StartMockRepos(t *testing.T, ctx *context.T) (*application.Envelope, func()) {
	envelope, appCleanup := StartApplicationRepository(ctx)
	binaryCleanup := StartBinaryRepository(ctx)

	return envelope, func() {
		binaryCleanup()
		appCleanup()
	}
}

// StartApplicationRepository sets up a server running the application
// repository.  It returns a pointer to the envelope that the repository returns
// to clients (so that it can be changed).  It also returns a cleanup function.
func StartApplicationRepository(ctx *context.T) (*application.Envelope, func()) {
	invoker := new(arInvoker)
	name := MockApplicationRepoName
	ctx, server, err := v23.WithNewServer(ctx, name, repository.ApplicationServer(invoker), security.AllowEveryone())
	if err != nil {
		ctx.Fatalf("NewServer(%v) failed: %v", name, err)
	}
	WaitForMount(ctx, ctx, name, server)
	return &invoker.envelope, func() {
		if err := server.Stop(); err != nil {
			ctx.Fatalf("Stop() failed: %v", err)
		}
	}
}

// arInvoker holds the state of an application repository invocation mock.  The
// mock returns the value of the wrapped envelope, which can be subsequently be
// changed at any time.  Client is responsible for synchronization if desired.
type arInvoker struct {
	envelope application.Envelope
}

// APPLICATION REPOSITORY INTERFACE IMPLEMENTATION
func (i *arInvoker) Match(ctx *context.T, _ rpc.ServerCall, profiles []string) (application.Envelope, error) {
	ctx.VI(1).Infof("Match()")
	if want := []string{"test-profile"}; !reflect.DeepEqual(profiles, want) {
		return application.Envelope{}, fmt.Errorf("Expected profiles %v, got %v", want, profiles)
	}
	return i.envelope, nil
}

func (i *arInvoker) GetPermissions(ctx *context.T, _ rpc.ServerCall) (perms access.Permissions, version string, err error) {
	return nil, "", nil
}

func (i *arInvoker) SetPermissions(ctx *context.T, _ rpc.ServerCall, perms access.Permissions, version string) error {
	return nil
}

func (i *arInvoker) TidyNow(_ *context.T, _ rpc.ServerCall) error {
	return nil
}

// brInvoker holds the state of a binary repository invocation mock.  It always
// serves the current running binary.
type brInvoker struct{}

// StartBinaryRepository sets up a server running the binary repository and
// returns a cleanup function.
func StartBinaryRepository(ctx *context.T) func() {
	name := MockBinaryRepoName
	ctx, server, err := v23.WithNewServer(ctx, name, repository.BinaryServer(new(brInvoker)), security.AllowEveryone())
	if err != nil {
		ctx.Fatalf("Serve(%q) failed: %v", name, err)
	}
	WaitForMount(ctx, ctx, name, server)
	return func() {
		if err := server.Stop(); err != nil {
			ctx.Fatalf("Stop() failed: %v", err)
		}
	}
}

// BINARY REPOSITORY INTERFACE IMPLEMENTATION

// TODO(toddw): Move the errors from dispatcher.go into a common location.
const pkgPath = "v.io/x/ref/services/device/deviced/internal/impl/utiltest"

var ErrOperationFailed = verror.Register(pkgPath+".OperationFailed", verror.NoRetry, "")

func (*brInvoker) Create(ctx *context.T, _ rpc.ServerCall, _ int32, _ repository.MediaInfo) error {
	ctx.VI(1).Infof("Create()")
	return nil
}

func (i *brInvoker) Delete(ctx *context.T, _ rpc.ServerCall) error {
	ctx.VI(1).Infof("Delete()")
	return nil
}

func mockBinaryBytesReader() (io.Reader, func(), error) {
	file, err := os.Open(os.Args[0])
	if err != nil {
		return nil, nil, err
	}
	cleanup := func() {
		file.Close()
	}
	return file, cleanup, nil
}

func (i *brInvoker) Download(ctx *context.T, call repository.BinaryDownloadServerCall, _ int32) error {
	ctx.VI(1).Infof("Download()")
	file, cleanup, err := mockBinaryBytesReader()
	if err != nil {
		ctx.Errorf("Open() failed: %v", err)
		return verror.New(ErrOperationFailed, ctx)
	}
	defer cleanup()
	bufferLength := 4096
	buffer := make([]byte, bufferLength)
	sender := call.SendStream()
	for {
		n, err := file.Read(buffer)
		switch err {
		case io.EOF:
			return nil
		case nil:
			if err := sender.Send(buffer[:n]); err != nil {
				ctx.Errorf("Send() failed: %v", err)
				return verror.New(ErrOperationFailed, ctx)
			}
		default:
			ctx.Errorf("Read() failed: %v", err)
			return verror.New(ErrOperationFailed, ctx)
		}
	}
}

func (*brInvoker) DownloadUrl(ctx *context.T, _ rpc.ServerCall) (string, int64, error) {
	ctx.VI(1).Infof("DownloadUrl()")
	return "", 0, nil
}

func (*brInvoker) Stat(ctx *context.T, call rpc.ServerCall) ([]binary.PartInfo, repository.MediaInfo, error) {
	ctx.VI(1).Infof("Stat()")
	h := md5.New()
	bytes, err := ioutil.ReadFile(os.Args[0])
	if err != nil {
		return []binary.PartInfo{}, repository.MediaInfo{}, verror.New(ErrOperationFailed, ctx)
	}
	h.Write(bytes)
	part := binary.PartInfo{Checksum: hex.EncodeToString(h.Sum(nil)), Size: int64(len(bytes))}
	return []binary.PartInfo{part}, repository.MediaInfo{Type: "application/octet-stream"}, nil
}

func (i *brInvoker) Upload(ctx *context.T, _ repository.BinaryUploadServerCall, _ int32) error {
	ctx.VI(1).Infof("Upload()")
	return nil
}

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

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