package unresolve

import (
	"fmt"
	"testing"

	"veyron2"
	"veyron2/context"
	"veyron2/ipc"
	"veyron2/naming"
	"veyron2/rt"
	"veyron2/security"
	mtidl "veyron2/services/mounttable"
	"veyron2/vlog"

	_ "veyron/lib/testutil"
	"veyron/lib/testutil/blackbox"
	mounttable "veyron/services/mounttable/lib"

	fortuneidl "veyron/examples/fortune"
)

func initRT(opts ...veyron2.ROpt) func() {
	return rt.Init(opts...).Cleanup
}

func createServer(name string, dispatcher ipc.Dispatcher, opts ...ipc.ServerOpt) (ipc.Server, string) {
	server, err := rt.R().NewServer(opts...)
	if err != nil {
		panic(fmt.Sprintf("r.NewServer failed with %v", err))
	}
	ep, err := server.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(fmt.Sprintf("server.Listen failed with %v", err))
	}
	if err := server.Serve(name, dispatcher); err != nil {
		panic(fmt.Sprintf("server.Serve failed with %v", err))
	}
	oa := naming.JoinAddressName(ep.String(), "")
	vlog.Infof("created %s -> %s", name, oa)
	return server, oa
}

func childMT(args []string) {
	defer initRT()()
	for _, arg := range args {
		server, _ := createMTServer(arg)
		defer server.Stop()
	}
	fmt.Println("ready")
	blackbox.WaitForEOFOnStdin()
}

func createMTServer(mp string) (ipc.Server, string) {
	mt, err := mounttable.NewMountTable("")
	if err != nil {
		panic(fmt.Sprintf("NewMountTable failed with %v", err))
	}
	return createServer(mp, mt, veyron2.ServesMountTableOpt(true))
}

func createMTClient(name string) mtidl.MountTable {
	client, err := mtidl.BindMountTable(name)
	if err != nil {
		panic(fmt.Sprintf("BindMountTable failed with %v", err))
	}
	return client
}

const fixedFortuneMessage = "Sooner than you think, you will be deeply dissatisfied with a fortune."

type fortune struct{}

func (*fortune) Get(ipc.ServerContext) (string, error) {
	return fixedFortuneMessage, nil
}

func (*fortune) Add(ipc.ServerContext, string) error {
	return nil
}

func childFortune(args []string) {
	defer initRT()()
	server, _ := createServer(args[0], ipc.LeafDispatcher(fortuneidl.NewServerFortune(new(fortune)), nil))
	defer server.Stop()
	for _, arg := range args[1:] {
		server.Serve(arg, nil)
	}
	fmt.Println("ready")
	blackbox.WaitForEOFOnStdin()
}

type fortuneCustomUnresolve struct {
	custom string
}

func (*fortuneCustomUnresolve) Get(ipc.ServerContext) (string, error) {
	return fixedFortuneMessage, nil
}

func (*fortuneCustomUnresolve) Add(ipc.ServerContext, string) error {
	return nil
}

func (*fortuneCustomUnresolve) UnresolveStep(context ipc.ServerContext) ([]string, error) {
	servers, err := rt.R().Namespace().ResolveToMountTable(rt.R().NewContext(), "I/want/to/know")
	if err != nil {
		return nil, err
	}
	var reply []string
	for _, s := range servers {
		r := naming.MakeResolvable(s)
		reply = append(reply, naming.Join(r, "the/future"))
	}
	return reply, nil
}

// Can't use the LeafDispatcher since it doesn't allow name suffixes.
type fortuned struct{ obj interface{} }

func (f *fortuned) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
	return ipc.ReflectInvoker(f.obj), nil, nil
}

func createFortuneCustomUnresolve(mp string) (ipc.Server, string) {
	server, oa := createServer(mp, &fortuned{fortuneidl.NewServerFortune(new(fortuneCustomUnresolve))})
	rt.R().Namespace().Mount(rt.R().NewContext(), "I/want/to/know", oa+"//", 0)
	rt.R().Namespace().Mount(rt.R().NewContext(), "tell/me", oa+"//", 0)
	return server, oa
}

func childFortuneCustomUnresolve(args []string) {
	defer initRT()()
	for _, arg := range args {
		server, _ := createFortuneCustomUnresolve(arg)
		defer server.Stop()
	}
	fmt.Println("ready")
	blackbox.WaitForEOFOnStdin()
}

func childFortuneNoIDL(args []string) {
	defer initRT()()
	for _, arg := range args {
		server, _ := createServer(arg, ipc.LeafDispatcher(new(fortuneNoIDL), nil))
		defer server.Stop()
	}
	fmt.Println("ready")
	blackbox.WaitForEOFOnStdin()
}

func createFortuneClient(rt veyron2.Runtime, name string) fortuneidl.Fortune {
	client, err := fortuneidl.BindFortune(name, rt.Client())
	if err != nil {
		panic(fmt.Sprintf("BindFortune failed with %v", err))
	}
	return client
}

type fortuneNoIDL struct{}

func (*fortuneNoIDL) Get(ipc.ServerCall) (string, error) {
	return fixedFortuneMessage, nil
}

func (*fortuneNoIDL) UnresolveStep(ipc.ServerCall) ([]string, error) {
	servers, err := rt.R().Namespace().ResolveToMountTable(rt.R().NewContext(), "g")
	if err != nil {
		return nil, err
	}
	var reply []string
	for _, s := range servers {
		r := naming.MakeResolvable(s)
		reply = append(reply, naming.Join(r, "fortune"))
	}
	return reply, nil
}

func resolveStep(t *testing.T, name string) string {
	client := createMTClient(name)
	results, suffix, err := client.ResolveStep(rt.R().NewContext())
	if err != nil {
		t.Errorf("ResolveStep on %q failed with %v", name, err)
		return ""
	}
	if len(results) != 1 {
		t.Errorf("Expected one result when resolving %q, got %q", name, results)
		return ""
	}
	return naming.Join(results[0].Server, suffix)
}

func resolve(t *testing.T, ns naming.Namespace, name string) string {
	results, err := ns.Resolve(rt.R().NewContext(), name)
	if err != nil {
		t.Errorf("Resolve failed with %v", err)
		return ""
	}
	if len(results) != 1 {
		t.Errorf("Expected one result when resolving %q, got %q", name, results)
		return ""
	}
	return results[0]
}

type unresolver interface {
	UnresolveStep(context.T, ...ipc.CallOpt) ([]string, error)
}

func unresolveStep(t *testing.T, ctx context.T, c unresolver) string {
	unres, err := c.UnresolveStep(ctx)
	if err != nil {
		t.Errorf("UnresolveStep failed with %v", err)
		return ""
	}
	if len(unres) != 1 {
		t.Errorf("c.UnresolveStep wanted 1 result, got: %q", unres)
		return ""
	}
	return unres[0]
}

func unresolve(t *testing.T, ns naming.Namespace, name string) string {
	results, err := ns.Unresolve(rt.R().NewContext(), name)
	if err != nil {
		t.Errorf("Unresolve failed with %v", err)
		return ""
	}
	if len(results) != 1 {
		t.Errorf("Expected one result when unresolving %q, got %q", name, results)
		return ""
	}
	return results[0]
}

func glob(t *testing.T, pattern string) []string {
	var replies []string
	rc, err := rt.R().Namespace().Glob(rt.R().NewContext(), pattern)
	if err != nil {
		t.Errorf("Glob(%s): err %v", pattern, err)
		return nil
	}
	for s := range rc {
		replies = append(replies, s.Name)
	}
	return replies
}
